mirror of
https://github.com/inventree/InvenTree.git
synced 2026-06-15 21:10:50 +00:00
Merge branch 'master' of https://github.com/inventree/InvenTree into pui-maintine-v7
This commit is contained in:
@@ -1,11 +1,17 @@
|
||||
"""InvenTree API version information."""
|
||||
|
||||
# InvenTree API version
|
||||
INVENTREE_API_VERSION = 190
|
||||
INVENTREE_API_VERSION = 192
|
||||
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
||||
|
||||
INVENTREE_API_TEXT = """
|
||||
|
||||
v192 - 2024-04-23 : https://github.com/inventree/InvenTree/pull/7106
|
||||
- Adds 'trackable' ordering option to BuildLineLabel API endpoint
|
||||
|
||||
v191 - 2024-04-22 : https://github.com/inventree/InvenTree/pull/7079
|
||||
- Adds API endpoints for Contenttype model
|
||||
|
||||
v190 - 2024-04-19 : https://github.com/inventree/InvenTree/pull/7024
|
||||
- Adds "active" field to the Company API endpoints
|
||||
- Allow company list to be filtered by "active" status
|
||||
|
||||
@@ -280,6 +280,8 @@ class InvenTreeMetadata(SimpleMetadata):
|
||||
# Special case for 'user' model
|
||||
if field_info['model'] == 'user':
|
||||
field_info['api_url'] = '/api/user/'
|
||||
elif field_info['model'] == 'contenttype':
|
||||
field_info['api_url'] = '/api/contenttype/'
|
||||
else:
|
||||
field_info['api_url'] = model.get_api_url()
|
||||
|
||||
|
||||
@@ -349,6 +349,7 @@ class BuildLineList(BuildLineEndpoint, ListCreateAPI):
|
||||
'optional',
|
||||
'unit_quantity',
|
||||
'available_stock',
|
||||
'trackable',
|
||||
]
|
||||
|
||||
ordering_field_aliases = {
|
||||
@@ -357,6 +358,7 @@ class BuildLineList(BuildLineEndpoint, ListCreateAPI):
|
||||
'unit_quantity': 'bom_item__quantity',
|
||||
'consumable': 'bom_item__consumable',
|
||||
'optional': 'bom_item__optional',
|
||||
'trackable': 'bom_item__sub_part__trackable',
|
||||
}
|
||||
|
||||
search_fields = [
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import json
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.http.response import HttpResponse
|
||||
from django.urls import include, path, re_path
|
||||
from django.utils.decorators import method_decorator
|
||||
@@ -619,6 +620,38 @@ class FlagDetail(RetrieveAPI):
|
||||
return {key: value}
|
||||
|
||||
|
||||
class ContentTypeList(ListAPI):
|
||||
"""List view for ContentTypes."""
|
||||
|
||||
queryset = ContentType.objects.all()
|
||||
serializer_class = common.serializers.ContentTypeSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
|
||||
class ContentTypeDetail(RetrieveAPI):
|
||||
"""Detail view for a ContentType model."""
|
||||
|
||||
queryset = ContentType.objects.all()
|
||||
serializer_class = common.serializers.ContentTypeSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
|
||||
@extend_schema(operation_id='contenttype_retrieve_model')
|
||||
class ContentTypeModelDetail(ContentTypeDetail):
|
||||
"""Detail view for a ContentType model."""
|
||||
|
||||
def get_object(self):
|
||||
"""Attempt to find a ContentType object with the provided key."""
|
||||
model_ref = self.kwargs.get('model', None)
|
||||
if model_ref:
|
||||
qs = self.filter_queryset(self.get_queryset())
|
||||
try:
|
||||
return qs.get(model=model_ref)
|
||||
except ContentType.DoesNotExist:
|
||||
raise NotFound()
|
||||
raise NotFound()
|
||||
|
||||
|
||||
settings_api_urls = [
|
||||
# User settings
|
||||
path(
|
||||
@@ -799,6 +832,21 @@ common_api_urls = [
|
||||
path('', AllStatusViews.as_view(), name='api-status-all'),
|
||||
]),
|
||||
),
|
||||
# Contenttype
|
||||
path(
|
||||
'contenttype/',
|
||||
include([
|
||||
path(
|
||||
'<int:pk>/', ContentTypeDetail.as_view(), name='api-contenttype-detail'
|
||||
),
|
||||
path(
|
||||
'<str:model>/',
|
||||
ContentTypeModelDetail.as_view(),
|
||||
name='api-contenttype-detail-modelname',
|
||||
),
|
||||
path('', ContentTypeList.as_view(), name='api-contenttype-list'),
|
||||
]),
|
||||
),
|
||||
]
|
||||
|
||||
admin_api_urls = [
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""JSON serializers for common components."""
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import OuterRef, Subquery
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
@@ -16,6 +17,7 @@ from InvenTree.serializers import (
|
||||
InvenTreeImageSerializerField,
|
||||
InvenTreeModelSerializer,
|
||||
)
|
||||
from plugin import registry as plugin_registry
|
||||
from users.serializers import OwnerSerializer
|
||||
|
||||
|
||||
@@ -303,6 +305,26 @@ class FlagSerializer(serializers.Serializer):
|
||||
return data
|
||||
|
||||
|
||||
class ContentTypeSerializer(serializers.Serializer):
|
||||
"""Serializer for ContentType models."""
|
||||
|
||||
pk = serializers.IntegerField(read_only=True)
|
||||
app_label = serializers.CharField(read_only=True)
|
||||
model = serializers.CharField(read_only=True)
|
||||
app_labeled_name = serializers.CharField(read_only=True)
|
||||
is_plugin = serializers.SerializerMethodField('get_is_plugin', read_only=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta options for ContentTypeSerializer."""
|
||||
|
||||
model = ContentType
|
||||
fields = ['pk', 'app_label', 'model', 'app_labeled_name', 'is_plugin']
|
||||
|
||||
def get_is_plugin(self, obj) -> bool:
|
||||
"""Return True if the model is a plugin model."""
|
||||
return obj.app_label in plugin_registry.installed_apps
|
||||
|
||||
|
||||
class CustomUnitSerializer(InvenTreeModelSerializer):
|
||||
"""DRF serializer for CustomUnit model."""
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ from http import HTTPStatus
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
@@ -1339,3 +1340,46 @@ class CustomUnitAPITest(InvenTreeAPITestCase):
|
||||
|
||||
for name in invalid_name_values:
|
||||
self.patch(url, {'name': name}, expected_code=400)
|
||||
|
||||
|
||||
class ContentTypeAPITest(InvenTreeAPITestCase):
|
||||
"""Unit tests for the ContentType API."""
|
||||
|
||||
def test_list(self):
|
||||
"""Test API list functionality."""
|
||||
response = self.get(reverse('api-contenttype-list'), expected_code=200)
|
||||
self.assertEqual(len(response.data), ContentType.objects.count())
|
||||
|
||||
def test_detail(self):
|
||||
"""Test API detail functionality."""
|
||||
ct = ContentType.objects.first()
|
||||
assert ct
|
||||
|
||||
response = self.get(
|
||||
reverse('api-contenttype-detail', kwargs={'pk': ct.pk}), expected_code=200
|
||||
)
|
||||
|
||||
self.assertEqual(response.data['app_label'], ct.app_label)
|
||||
self.assertEqual(response.data['model'], ct.model)
|
||||
|
||||
# Test with model name
|
||||
response = self.get(
|
||||
reverse('api-contenttype-detail-modelname', kwargs={'model': ct.model}),
|
||||
expected_code=200,
|
||||
)
|
||||
self.assertEqual(response.data['app_label'], ct.app_label)
|
||||
self.assertEqual(response.data['model'], ct.model)
|
||||
|
||||
# Test non-existent model
|
||||
self.get(
|
||||
reverse(
|
||||
'api-contenttype-detail-modelname', kwargs={'model': 'nonexistent'}
|
||||
),
|
||||
expected_code=404,
|
||||
)
|
||||
|
||||
# PK should not work on model name endpoint
|
||||
self.get(
|
||||
reverse('api-contenttype-detail-modelname', kwargs={'model': None}),
|
||||
expected_code=404,
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1459,9 +1459,11 @@ class PurchaseOrderLineItem(OrderLineItem):
|
||||
def update_pricing(self):
|
||||
"""Update pricing information based on the supplier part data."""
|
||||
if self.part:
|
||||
price = self.part.get_price(self.quantity)
|
||||
price = self.part.get_price(
|
||||
self.quantity, currency=self.purchase_price_currency
|
||||
)
|
||||
|
||||
if price is None:
|
||||
if price is None or self.quantity == 0:
|
||||
return
|
||||
|
||||
self.purchase_price = Decimal(price) / Decimal(self.quantity)
|
||||
|
||||
@@ -2436,11 +2436,9 @@ function loadBuildLineTable(table, build_id, options={}) {
|
||||
params.build = build_id;
|
||||
|
||||
if (output) {
|
||||
params.tracked = true;
|
||||
params.output = output;
|
||||
name += `-${output}`;
|
||||
} else {
|
||||
// Default to untracked parts for the build
|
||||
params.tracked = false;
|
||||
}
|
||||
|
||||
let filters = loadTableFilters('buildlines', params);
|
||||
@@ -2649,7 +2647,11 @@ function loadBuildLineTable(table, build_id, options={}) {
|
||||
|
||||
if (row.part_detail.trackable && !options.output) {
|
||||
// Tracked parts must be allocated to a specific build output
|
||||
return `<em>{% trans "Tracked item" %}</em>`;
|
||||
return `
|
||||
<div>
|
||||
<em>{% trans "Tracked item" %}</em>
|
||||
<span title='{% trans "Allocate tracked items against individual build outputs" %}' class='fas fa-info-circle icon-blue' />
|
||||
</div>`;
|
||||
}
|
||||
|
||||
if (row.allocated < row.quantity) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Dev requirements for InvenTree
|
||||
-c requirements.txt
|
||||
coverage[toml] # Unit test coverage
|
||||
coveralls==2.1.2 # Coveralls linking (for tracking coverage) # PINNED 2022-06-28 - Old version needed for correct upload
|
||||
django-admin-shell # Remote shell access
|
||||
django-querycount # Display number of URL queries for requests
|
||||
django-slowtests # Show which unit tests are running slowly
|
||||
|
||||
@@ -1,90 +1,413 @@
|
||||
# This file was autogenerated by uv via the following command:
|
||||
# uv pip compile src/backend/requirements-dev.in -o src/backend/requirements-dev.txt --python-version=3.9 --no-strip-extras
|
||||
asgiref==3.8.1
|
||||
# uv pip compile src/backend/requirements-dev.in -o src/backend/requirements-dev.txt --python-version=3.9 --no-strip-extras --generate-hashes
|
||||
asgiref==3.8.1 \
|
||||
--hash=sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47 \
|
||||
--hash=sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590
|
||||
# via django
|
||||
build==1.2.1
|
||||
build==1.2.1 \
|
||||
--hash=sha256:526263f4870c26f26c433545579475377b2b7588b6f1eac76a001e873ae3e19d \
|
||||
--hash=sha256:75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4
|
||||
# via pip-tools
|
||||
certifi==2024.2.2
|
||||
# via requests
|
||||
cffi==1.16.0
|
||||
cffi==1.16.0 \
|
||||
--hash=sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc \
|
||||
--hash=sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a \
|
||||
--hash=sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 \
|
||||
--hash=sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab \
|
||||
--hash=sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520 \
|
||||
--hash=sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36 \
|
||||
--hash=sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743 \
|
||||
--hash=sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8 \
|
||||
--hash=sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed \
|
||||
--hash=sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684 \
|
||||
--hash=sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56 \
|
||||
--hash=sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324 \
|
||||
--hash=sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d \
|
||||
--hash=sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235 \
|
||||
--hash=sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e \
|
||||
--hash=sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088 \
|
||||
--hash=sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000 \
|
||||
--hash=sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7 \
|
||||
--hash=sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e \
|
||||
--hash=sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673 \
|
||||
--hash=sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c \
|
||||
--hash=sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe \
|
||||
--hash=sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2 \
|
||||
--hash=sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098 \
|
||||
--hash=sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8 \
|
||||
--hash=sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a \
|
||||
--hash=sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0 \
|
||||
--hash=sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b \
|
||||
--hash=sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896 \
|
||||
--hash=sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e \
|
||||
--hash=sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9 \
|
||||
--hash=sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2 \
|
||||
--hash=sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b \
|
||||
--hash=sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6 \
|
||||
--hash=sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 \
|
||||
--hash=sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f \
|
||||
--hash=sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0 \
|
||||
--hash=sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4 \
|
||||
--hash=sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc \
|
||||
--hash=sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 \
|
||||
--hash=sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba \
|
||||
--hash=sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872 \
|
||||
--hash=sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb \
|
||||
--hash=sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614 \
|
||||
--hash=sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1 \
|
||||
--hash=sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d \
|
||||
--hash=sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969 \
|
||||
--hash=sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b \
|
||||
--hash=sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4 \
|
||||
--hash=sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627 \
|
||||
--hash=sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956 \
|
||||
--hash=sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357
|
||||
# via cryptography
|
||||
cfgv==3.4.0
|
||||
cfgv==3.4.0 \
|
||||
--hash=sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9 \
|
||||
--hash=sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560
|
||||
# via pre-commit
|
||||
charset-normalizer==3.3.2
|
||||
# via
|
||||
# pdfminer-six
|
||||
# requests
|
||||
click==8.1.7
|
||||
# via pip-tools
|
||||
coverage[toml]==5.5
|
||||
# via coveralls
|
||||
coveralls==2.1.2
|
||||
cryptography==42.0.5
|
||||
charset-normalizer==3.3.2 \
|
||||
--hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \
|
||||
--hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \
|
||||
--hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \
|
||||
--hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \
|
||||
--hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \
|
||||
--hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \
|
||||
--hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \
|
||||
--hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \
|
||||
--hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \
|
||||
--hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \
|
||||
--hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \
|
||||
--hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \
|
||||
--hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \
|
||||
--hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \
|
||||
--hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \
|
||||
--hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \
|
||||
--hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \
|
||||
--hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \
|
||||
--hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \
|
||||
--hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \
|
||||
--hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \
|
||||
--hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \
|
||||
--hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \
|
||||
--hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \
|
||||
--hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \
|
||||
--hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \
|
||||
--hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \
|
||||
--hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \
|
||||
--hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \
|
||||
--hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \
|
||||
--hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \
|
||||
--hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \
|
||||
--hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \
|
||||
--hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \
|
||||
--hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \
|
||||
--hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \
|
||||
--hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \
|
||||
--hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \
|
||||
--hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \
|
||||
--hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \
|
||||
--hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \
|
||||
--hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \
|
||||
--hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \
|
||||
--hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \
|
||||
--hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \
|
||||
--hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \
|
||||
--hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \
|
||||
--hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \
|
||||
--hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \
|
||||
--hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \
|
||||
--hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \
|
||||
--hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \
|
||||
--hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \
|
||||
--hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \
|
||||
--hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \
|
||||
--hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \
|
||||
--hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \
|
||||
--hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \
|
||||
--hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \
|
||||
--hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \
|
||||
--hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \
|
||||
--hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \
|
||||
--hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \
|
||||
--hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \
|
||||
--hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \
|
||||
--hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \
|
||||
--hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \
|
||||
--hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \
|
||||
--hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \
|
||||
--hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \
|
||||
--hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \
|
||||
--hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \
|
||||
--hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \
|
||||
--hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \
|
||||
--hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \
|
||||
--hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \
|
||||
--hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \
|
||||
--hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \
|
||||
--hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \
|
||||
--hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \
|
||||
--hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \
|
||||
--hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \
|
||||
--hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \
|
||||
--hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \
|
||||
--hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \
|
||||
--hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \
|
||||
--hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \
|
||||
--hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \
|
||||
--hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \
|
||||
--hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561
|
||||
# via pdfminer-six
|
||||
distlib==0.3.8
|
||||
click==8.1.7 \
|
||||
--hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \
|
||||
--hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de
|
||||
# via pip-tools
|
||||
coverage[toml]==5.5 \
|
||||
--hash=sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c \
|
||||
--hash=sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6 \
|
||||
--hash=sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45 \
|
||||
--hash=sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a \
|
||||
--hash=sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03 \
|
||||
--hash=sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529 \
|
||||
--hash=sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a \
|
||||
--hash=sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a \
|
||||
--hash=sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2 \
|
||||
--hash=sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6 \
|
||||
--hash=sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759 \
|
||||
--hash=sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53 \
|
||||
--hash=sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a \
|
||||
--hash=sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4 \
|
||||
--hash=sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff \
|
||||
--hash=sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502 \
|
||||
--hash=sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793 \
|
||||
--hash=sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb \
|
||||
--hash=sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905 \
|
||||
--hash=sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821 \
|
||||
--hash=sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b \
|
||||
--hash=sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81 \
|
||||
--hash=sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0 \
|
||||
--hash=sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b \
|
||||
--hash=sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3 \
|
||||
--hash=sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184 \
|
||||
--hash=sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701 \
|
||||
--hash=sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a \
|
||||
--hash=sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82 \
|
||||
--hash=sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638 \
|
||||
--hash=sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5 \
|
||||
--hash=sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083 \
|
||||
--hash=sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6 \
|
||||
--hash=sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90 \
|
||||
--hash=sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465 \
|
||||
--hash=sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a \
|
||||
--hash=sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3 \
|
||||
--hash=sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e \
|
||||
--hash=sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066 \
|
||||
--hash=sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf \
|
||||
--hash=sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b \
|
||||
--hash=sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae \
|
||||
--hash=sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669 \
|
||||
--hash=sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873 \
|
||||
--hash=sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b \
|
||||
--hash=sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6 \
|
||||
--hash=sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb \
|
||||
--hash=sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160 \
|
||||
--hash=sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c \
|
||||
--hash=sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079 \
|
||||
--hash=sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d \
|
||||
--hash=sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6
|
||||
cryptography==42.0.5 \
|
||||
--hash=sha256:0270572b8bd2c833c3981724b8ee9747b3ec96f699a9665470018594301439ee \
|
||||
--hash=sha256:111a0d8553afcf8eb02a4fea6ca4f59d48ddb34497aa8706a6cf536f1a5ec576 \
|
||||
--hash=sha256:16a48c23a62a2f4a285699dba2e4ff2d1cff3115b9df052cdd976a18856d8e3d \
|
||||
--hash=sha256:1b95b98b0d2af784078fa69f637135e3c317091b615cd0905f8b8a087e86fa30 \
|
||||
--hash=sha256:1f71c10d1e88467126f0efd484bd44bca5e14c664ec2ede64c32f20875c0d413 \
|
||||
--hash=sha256:2424ff4c4ac7f6b8177b53c17ed5d8fa74ae5955656867f5a8affaca36a27abb \
|
||||
--hash=sha256:2bce03af1ce5a5567ab89bd90d11e7bbdff56b8af3acbbec1faded8f44cb06da \
|
||||
--hash=sha256:329906dcc7b20ff3cad13c069a78124ed8247adcac44b10bea1130e36caae0b4 \
|
||||
--hash=sha256:37dd623507659e08be98eec89323469e8c7b4c1407c85112634ae3dbdb926fdd \
|
||||
--hash=sha256:3eaafe47ec0d0ffcc9349e1708be2aaea4c6dd4978d76bf6eb0cb2c13636c6fc \
|
||||
--hash=sha256:5e6275c09d2badf57aea3afa80d975444f4be8d3bc58f7f80d2a484c6f9485c8 \
|
||||
--hash=sha256:6fe07eec95dfd477eb9530aef5bead34fec819b3aaf6c5bd6d20565da607bfe1 \
|
||||
--hash=sha256:7367d7b2eca6513681127ebad53b2582911d1736dc2ffc19f2c3ae49997496bc \
|
||||
--hash=sha256:7cde5f38e614f55e28d831754e8a3bacf9ace5d1566235e39d91b35502d6936e \
|
||||
--hash=sha256:9481ffe3cf013b71b2428b905c4f7a9a4f76ec03065b05ff499bb5682a8d9ad8 \
|
||||
--hash=sha256:98d8dc6d012b82287f2c3d26ce1d2dd130ec200c8679b6213b3c73c08b2b7940 \
|
||||
--hash=sha256:a011a644f6d7d03736214d38832e030d8268bcff4a41f728e6030325fea3e400 \
|
||||
--hash=sha256:a2913c5375154b6ef2e91c10b5720ea6e21007412f6437504ffea2109b5a33d7 \
|
||||
--hash=sha256:a30596bae9403a342c978fb47d9b0ee277699fa53bbafad14706af51fe543d16 \
|
||||
--hash=sha256:b03c2ae5d2f0fc05f9a2c0c997e1bc18c8229f392234e8a0194f202169ccd278 \
|
||||
--hash=sha256:b6cd2203306b63e41acdf39aa93b86fb566049aeb6dc489b70e34bcd07adca74 \
|
||||
--hash=sha256:b7ffe927ee6531c78f81aa17e684e2ff617daeba7f189f911065b2ea2d526dec \
|
||||
--hash=sha256:b8cac287fafc4ad485b8a9b67d0ee80c66bf3574f655d3b97ef2e1082360faf1 \
|
||||
--hash=sha256:ba334e6e4b1d92442b75ddacc615c5476d4ad55cc29b15d590cc6b86efa487e2 \
|
||||
--hash=sha256:ba3e4a42397c25b7ff88cdec6e2a16c2be18720f317506ee25210f6d31925f9c \
|
||||
--hash=sha256:c41fb5e6a5fe9ebcd58ca3abfeb51dffb5d83d6775405305bfa8715b76521922 \
|
||||
--hash=sha256:cd2030f6650c089aeb304cf093f3244d34745ce0cfcc39f20c6fbfe030102e2a \
|
||||
--hash=sha256:cd65d75953847815962c84a4654a84850b2bb4aed3f26fadcc1c13892e1e29f6 \
|
||||
--hash=sha256:e4985a790f921508f36f81831817cbc03b102d643b5fcb81cd33df3fa291a1a1 \
|
||||
--hash=sha256:e807b3188f9eb0eaa7bbb579b462c5ace579f1cedb28107ce8b48a9f7ad3679e \
|
||||
--hash=sha256:f12764b8fffc7a123f641d7d049d382b73f96a34117e0b637b80643169cec8ac \
|
||||
--hash=sha256:f8837fe1d6ac4a8052a9a8ddab256bc006242696f03368a4009be7ee3075cdb7
|
||||
# via pdfminer-six
|
||||
distlib==0.3.8 \
|
||||
--hash=sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 \
|
||||
--hash=sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64
|
||||
# via virtualenv
|
||||
django==4.2.11
|
||||
django==4.2.11 \
|
||||
--hash=sha256:6e6ff3db2d8dd0c986b4eec8554c8e4f919b5c1ff62a5b4390c17aff2ed6e5c4 \
|
||||
--hash=sha256:ddc24a0a8280a0430baa37aff11f28574720af05888c62b7cfe71d219f4599d3
|
||||
# via
|
||||
# django-admin-shell
|
||||
# django-slowtests
|
||||
django-admin-shell==2.0.1
|
||||
django-querycount==0.8.3
|
||||
django-slowtests==1.1.1
|
||||
django-test-migrations==1.3.0
|
||||
docopt==0.6.2
|
||||
# via coveralls
|
||||
filelock==3.13.3
|
||||
django-admin-shell==2.0.1 \
|
||||
--hash=sha256:334a651e53ae4f59d0d279d7ede7dc5ed7a7733d4d093765b447dca5274c7b30 \
|
||||
--hash=sha256:b129e282ebd581c2099c0504edf081259728b3a504b40c5784d0457b8cb41470
|
||||
django-querycount==0.8.3 \
|
||||
--hash=sha256:0782484e8a1bd29498fa0195a67106e47cdcc98fafe80cebb1991964077cb694
|
||||
django-slowtests==1.1.1 \
|
||||
--hash=sha256:3c6936d420c9df444ac03625b41d97de043c662bbde61fbcd33e4cd407d0c247
|
||||
django-test-migrations==1.3.0 \
|
||||
--hash=sha256:b42edb1af481e08c9d91c95aa9b373e76e905a931bc19c086ec00a6cb936876e \
|
||||
--hash=sha256:b52b29475f9a1bcaa4512f2ec8fad08b5f470cf1cf522e86b7d950252fb6fbf1
|
||||
filelock==3.13.3 \
|
||||
--hash=sha256:5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb \
|
||||
--hash=sha256:a79895a25bbefdf55d1a2a0a80968f7dbb28edcd6d4234a0afb3f37ecde4b546
|
||||
# via virtualenv
|
||||
identify==2.5.35
|
||||
identify==2.5.35 \
|
||||
--hash=sha256:10a7ca245cfcd756a554a7288159f72ff105ad233c7c4b9c6f0f4d108f5f6791 \
|
||||
--hash=sha256:c4de0081837b211594f8e877a6b4fad7ca32bbfc1a9307fdd61c28bfe923f13e
|
||||
# via pre-commit
|
||||
idna==3.6
|
||||
# via requests
|
||||
importlib-metadata==7.0.0
|
||||
importlib-metadata==7.0.0 \
|
||||
--hash=sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7 \
|
||||
--hash=sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67
|
||||
# via build
|
||||
isort==5.13.2
|
||||
nodeenv==1.8.0
|
||||
isort==5.13.2 \
|
||||
--hash=sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109 \
|
||||
--hash=sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6
|
||||
nodeenv==1.8.0 \
|
||||
--hash=sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2 \
|
||||
--hash=sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec
|
||||
# via pre-commit
|
||||
packaging==24.0
|
||||
packaging==24.0 \
|
||||
--hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \
|
||||
--hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9
|
||||
# via build
|
||||
pdfminer-six==20231228
|
||||
pip==24.0
|
||||
pdfminer-six==20231228 \
|
||||
--hash=sha256:6004da3ad1a7a4d45930cb950393df89b068e73be365a6ff64a838d37bcb08c4 \
|
||||
--hash=sha256:e8d3c3310e6fbc1fe414090123ab01351634b4ecb021232206c4c9a8ca3e3b8f
|
||||
pip==24.0 \
|
||||
--hash=sha256:ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc \
|
||||
--hash=sha256:ea9bd1a847e8c5774a5777bb398c19e80bcd4e2aa16a4b301b718fe6f593aba2
|
||||
# via pip-tools
|
||||
pip-tools==7.4.1
|
||||
platformdirs==4.2.0
|
||||
pip-tools==7.4.1 \
|
||||
--hash=sha256:4c690e5fbae2f21e87843e89c26191f0d9454f362d8acdbd695716493ec8b3a9 \
|
||||
--hash=sha256:864826f5073864450e24dbeeb85ce3920cdfb09848a3d69ebf537b521f14bcc9
|
||||
platformdirs==4.2.0 \
|
||||
--hash=sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068 \
|
||||
--hash=sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768
|
||||
# via virtualenv
|
||||
pre-commit==3.7.0
|
||||
pycparser==2.22
|
||||
pre-commit==3.7.0 \
|
||||
--hash=sha256:5eae9e10c2b5ac51577c3452ec0a490455c45a0533f7960f993a0d01e59decab \
|
||||
--hash=sha256:e209d61b8acdcf742404408531f0c37d49d2c734fd7cff2d6076083d191cb060
|
||||
pycparser==2.22 \
|
||||
--hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \
|
||||
--hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc
|
||||
# via cffi
|
||||
pyproject-hooks==1.0.0
|
||||
pyproject-hooks==1.0.0 \
|
||||
--hash=sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8 \
|
||||
--hash=sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5
|
||||
# via
|
||||
# build
|
||||
# pip-tools
|
||||
pyyaml==6.0.1
|
||||
pyyaml==6.0.1 \
|
||||
--hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
|
||||
--hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \
|
||||
--hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \
|
||||
--hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \
|
||||
--hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \
|
||||
--hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \
|
||||
--hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \
|
||||
--hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \
|
||||
--hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \
|
||||
--hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \
|
||||
--hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \
|
||||
--hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \
|
||||
--hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \
|
||||
--hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \
|
||||
--hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \
|
||||
--hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \
|
||||
--hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \
|
||||
--hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \
|
||||
--hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \
|
||||
--hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \
|
||||
--hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \
|
||||
--hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \
|
||||
--hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \
|
||||
--hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \
|
||||
--hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \
|
||||
--hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \
|
||||
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
|
||||
--hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
|
||||
--hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
|
||||
--hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
|
||||
--hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
|
||||
--hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
|
||||
--hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
|
||||
--hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \
|
||||
--hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \
|
||||
--hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \
|
||||
--hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \
|
||||
--hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \
|
||||
--hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \
|
||||
--hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \
|
||||
--hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \
|
||||
--hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \
|
||||
--hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \
|
||||
--hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \
|
||||
--hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \
|
||||
--hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \
|
||||
--hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \
|
||||
--hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \
|
||||
--hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \
|
||||
--hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \
|
||||
--hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f
|
||||
# via pre-commit
|
||||
requests==2.31.0
|
||||
# via coveralls
|
||||
setuptools==69.5.1
|
||||
setuptools==69.5.1 \
|
||||
--hash=sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987 \
|
||||
--hash=sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32
|
||||
# via
|
||||
# nodeenv
|
||||
# pip-tools
|
||||
sqlparse==0.4.4
|
||||
sqlparse==0.4.4 \
|
||||
--hash=sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3 \
|
||||
--hash=sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c
|
||||
# via django
|
||||
toml==0.10.2
|
||||
toml==0.10.2 \
|
||||
--hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \
|
||||
--hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f
|
||||
# via coverage
|
||||
tomli==2.0.1
|
||||
tomli==2.0.1 \
|
||||
--hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
|
||||
--hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
|
||||
# via
|
||||
# build
|
||||
# pip-tools
|
||||
# pyproject-hooks
|
||||
typing-extensions==4.11.0
|
||||
typing-extensions==4.11.0 \
|
||||
--hash=sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0 \
|
||||
--hash=sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a
|
||||
# via
|
||||
# asgiref
|
||||
# django-test-migrations
|
||||
urllib3==2.2.1
|
||||
# via requests
|
||||
virtualenv==20.25.1
|
||||
virtualenv==20.25.1 \
|
||||
--hash=sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a \
|
||||
--hash=sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197
|
||||
# via pre-commit
|
||||
wheel==0.43.0
|
||||
wheel==0.43.0 \
|
||||
--hash=sha256:465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85 \
|
||||
--hash=sha256:55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81
|
||||
# via pip-tools
|
||||
zipp==3.18.1
|
||||
zipp==3.18.1 \
|
||||
--hash=sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b \
|
||||
--hash=sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715
|
||||
# via importlib-metadata
|
||||
|
||||
+1392
-136
File diff suppressed because it is too large
Load Diff
@@ -37,6 +37,9 @@ export default defineConfig({
|
||||
},
|
||||
{
|
||||
command: 'invoke server -a 127.0.0.1:8000',
|
||||
env: {
|
||||
INVENTREE_DEBUG: 'True'
|
||||
},
|
||||
url: 'http://127.0.0.1:8000/api/',
|
||||
reuseExistingServer: !process.env.CI,
|
||||
stdout: 'pipe',
|
||||
|
||||
@@ -19,3 +19,16 @@ export function isTrue(value: any): boolean {
|
||||
|
||||
return ['true', 'yes', '1', 'on', 't', 'y'].includes(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve a nested item in an object.
|
||||
* Returns the resolved item, if it exists.
|
||||
*
|
||||
* e.g. resolveItem(data, "sub.key.accessor")
|
||||
*
|
||||
* Allows for retrieval of nested items in an object.
|
||||
*/
|
||||
export function resolveItem(obj: any, path: string): any {
|
||||
let properties = path.split('.');
|
||||
return properties.reduce((prev, curr) => prev?.[curr], obj);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -203,8 +203,7 @@ export default function BuildDetail() {
|
||||
content: build?.pk ? (
|
||||
<BuildLineTable
|
||||
params={{
|
||||
build: id,
|
||||
tracked: false
|
||||
build: id
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
|
||||
@@ -37,7 +37,13 @@ import { InvenTreeTable } from '../../../tables/InvenTreeTable';
|
||||
import { NoPricingData } from './PricingPanel';
|
||||
|
||||
// Display BOM data as a pie chart
|
||||
function BomPieChart({ data, currency }: { data: any[]; currency: string }) {
|
||||
function BomPieChart({
|
||||
data,
|
||||
currency
|
||||
}: {
|
||||
readonly data: any[];
|
||||
readonly currency: string;
|
||||
}) {
|
||||
return (
|
||||
<ResponsiveContainer width="100%" height={500}>
|
||||
<PieChart>
|
||||
@@ -78,7 +84,13 @@ function BomPieChart({ data, currency }: { data: any[]; currency: string }) {
|
||||
}
|
||||
|
||||
// Display BOM data as a bar chart
|
||||
function BomBarChart({ data, currency }: { data: any[]; currency: string }) {
|
||||
function BomBarChart({
|
||||
data,
|
||||
currency
|
||||
}: {
|
||||
readonly data: any[];
|
||||
readonly currency: string;
|
||||
}) {
|
||||
return (
|
||||
<ResponsiveContainer width="100%" height={500}>
|
||||
<BarChart data={data}>
|
||||
@@ -113,8 +125,8 @@ export default function BomPricingPanel({
|
||||
part,
|
||||
pricing
|
||||
}: {
|
||||
part: any;
|
||||
pricing: any;
|
||||
readonly part: any;
|
||||
readonly pricing: any;
|
||||
}): ReactNode {
|
||||
const table = useTable('pricing-bom');
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ export default function PricingOverviewPanel({
|
||||
<DataTable records={overviewData} columns={columns} />
|
||||
</Stack>
|
||||
<ResponsiveContainer width="100%" height={500}>
|
||||
<BarChart data={overviewData}>
|
||||
<BarChart data={overviewData} id="pricing-overview-chart">
|
||||
<XAxis dataKey="title" />
|
||||
<YAxis
|
||||
tickFormatter={(value, index) =>
|
||||
|
||||
@@ -43,9 +43,9 @@ export default function PricingPanel({
|
||||
label: panelOptions;
|
||||
title: string;
|
||||
visible: boolean;
|
||||
disabled?: boolean | undefined;
|
||||
disabled?: boolean;
|
||||
}): ReactNode {
|
||||
const is_disabled = disabled === undefined ? false : disabled;
|
||||
const is_disabled = disabled ?? false;
|
||||
return (
|
||||
visible && (
|
||||
<Accordion.Item value={label} id={label}>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
import { t } from '@lingui/macro';
|
||||
import { Anchor } from '@mantine/core';
|
||||
import { access } from 'fs';
|
||||
|
||||
import { YesNoButton } from '../components/buttons/YesNoButton';
|
||||
import { Thumbnail } from '../components/images/Thumbnail';
|
||||
@@ -11,6 +12,7 @@ import { TableStatusRenderer } from '../components/render/StatusRenderer';
|
||||
import { RenderOwner } from '../components/render/User';
|
||||
import { formatCurrency, renderDate } from '../defaults/formatters';
|
||||
import { ModelType } from '../enums/ModelType';
|
||||
import { resolveItem } from '../functions/conversion';
|
||||
import { cancelEvent } from '../functions/events';
|
||||
import { TableColumn } from './Column';
|
||||
import { ProjectCodeHoverCard } from './TableHoverCard';
|
||||
@@ -29,19 +31,24 @@ export function BooleanColumn({
|
||||
accessor,
|
||||
title,
|
||||
sortable,
|
||||
switchable
|
||||
switchable,
|
||||
ordering
|
||||
}: {
|
||||
accessor: string;
|
||||
title?: string;
|
||||
ordering?: string;
|
||||
sortable?: boolean;
|
||||
switchable?: boolean;
|
||||
}): TableColumn {
|
||||
return {
|
||||
accessor: accessor,
|
||||
title: title,
|
||||
ordering: ordering,
|
||||
sortable: sortable ?? true,
|
||||
switchable: switchable ?? true,
|
||||
render: (record: any) => <YesNoButton value={record[accessor]} />
|
||||
render: (record: any) => (
|
||||
<YesNoButton value={resolveItem(record, accessor)} />
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -71,7 +78,7 @@ export function LinkColumn({
|
||||
accessor: accessor,
|
||||
sortable: false,
|
||||
render: (record: any) => {
|
||||
let url = record[accessor];
|
||||
let url = resolveItem(record, accessor);
|
||||
|
||||
if (!url) {
|
||||
return '-';
|
||||
|
||||
@@ -33,6 +33,7 @@ import { ActionButton } from '../components/buttons/ActionButton';
|
||||
import { ButtonMenu } from '../components/buttons/ButtonMenu';
|
||||
import { ApiFormFieldSet } from '../components/forms/fields/ApiFormField';
|
||||
import { ModelType } from '../enums/ModelType';
|
||||
import { resolveItem } from '../functions/conversion';
|
||||
import { extractAvailableFields, mapFields } from '../functions/forms';
|
||||
import { getDetailUrl } from '../functions/urls';
|
||||
import { TableState } from '../hooks/UseTable';
|
||||
@@ -524,7 +525,8 @@ export function InvenTreeTable<T = any>({
|
||||
// If a custom row click handler is provided, use that
|
||||
props.onRowClick(record, index, event);
|
||||
} else if (tableProps.modelType) {
|
||||
const pk = record?.[tableProps.modelField ?? 'pk'];
|
||||
const accessor = tableProps.modelField ?? 'pk';
|
||||
const pk = resolveItem(record, accessor);
|
||||
|
||||
if (pk) {
|
||||
// If a model type is provided, navigate to the detail view for that model
|
||||
|
||||
@@ -6,13 +6,11 @@ import {
|
||||
IconTool
|
||||
} from '@tabler/icons-react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { PartHoverCard } from '../../components/images/Thumbnail';
|
||||
import { ProgressBar } from '../../components/items/ProgressBar';
|
||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||
import { ModelType } from '../../enums/ModelType';
|
||||
import { getDetailUrl } from '../../functions/urls';
|
||||
import { useTable } from '../../hooks/UseTable';
|
||||
import { apiUrl } from '../../states/ApiState';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
@@ -25,7 +23,6 @@ import { TableHoverCard } from '../TableHoverCard';
|
||||
export default function BuildLineTable({ params = {} }: { params?: any }) {
|
||||
const table = useTable('buildline');
|
||||
const user = useUserState();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const tableFilters: TableFilter[] = useMemo(() => {
|
||||
return [
|
||||
@@ -48,6 +45,11 @@ export default function BuildLineTable({ params = {} }: { params?: any }) {
|
||||
name: 'optional',
|
||||
label: t`Optional`,
|
||||
description: t`Show optional lines`
|
||||
},
|
||||
{
|
||||
name: 'tracked',
|
||||
label: t`Tracked`,
|
||||
description: t`Show tracked lines`
|
||||
}
|
||||
];
|
||||
}, []);
|
||||
@@ -126,18 +128,28 @@ export default function BuildLineTable({ params = {} }: { params?: any }) {
|
||||
return [
|
||||
{
|
||||
accessor: 'bom_item',
|
||||
ordering: 'part',
|
||||
sortable: true,
|
||||
switchable: false,
|
||||
render: (record: any) => <PartHoverCard part={record.part_detail} />
|
||||
},
|
||||
{
|
||||
accessor: 'bom_item_detail.reference'
|
||||
accessor: 'bom_item_detail.reference',
|
||||
ordering: 'reference',
|
||||
sortable: true,
|
||||
title: t`Reference`
|
||||
},
|
||||
BooleanColumn({
|
||||
accessor: 'bom_item_detail.consumable'
|
||||
accessor: 'bom_item_detail.consumable',
|
||||
ordering: 'consumable'
|
||||
}),
|
||||
BooleanColumn({
|
||||
accessor: 'bom_item_detail.optional'
|
||||
accessor: 'bom_item_detail.optional',
|
||||
ordering: 'optional'
|
||||
}),
|
||||
BooleanColumn({
|
||||
accessor: 'part_detail.trackable',
|
||||
ordering: 'trackable'
|
||||
}),
|
||||
{
|
||||
accessor: 'bom_item_detail.quantity',
|
||||
@@ -202,6 +214,11 @@ export default function BuildLineTable({ params = {} }: { params?: any }) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Tracked items must be allocated to a particular output
|
||||
if (record?.part_detail?.trackable) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
icon: <IconArrowRight />,
|
||||
@@ -238,11 +255,8 @@ export default function BuildLineTable({ params = {} }: { params?: any }) {
|
||||
},
|
||||
tableFilters: tableFilters,
|
||||
rowActions: rowActions,
|
||||
onRowClick: (row: any) => {
|
||||
if (row?.part_detail?.pk) {
|
||||
navigate(getDetailUrl(ModelType.part, row.part_detail.pk));
|
||||
}
|
||||
}
|
||||
modelType: ModelType.part,
|
||||
modelField: 'part_detail.pk'
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export const classicUrl = 'http://127.0.0.1:8000';
|
||||
|
||||
export const baseUrl = `${classicUrl}/platform`;
|
||||
export const baseUrl = './platform';
|
||||
export const loginUrl = `${baseUrl}/login`;
|
||||
export const logoutUrl = `${baseUrl}/logout`;
|
||||
export const homeUrl = `${baseUrl}/home`;
|
||||
|
||||
@@ -25,13 +25,15 @@ export const doLogin = async (page, username?: string, password?: string) => {
|
||||
export const doQuickLogin = async (
|
||||
page,
|
||||
username?: string,
|
||||
password?: string
|
||||
password?: string,
|
||||
url?: string
|
||||
) => {
|
||||
username = username ?? user.username;
|
||||
password = password ?? user.password;
|
||||
url = url ?? baseUrl;
|
||||
|
||||
// await page.goto(logoutUrl);
|
||||
await page.goto(`${baseUrl}/login/?login=${username}&password=${password}`);
|
||||
await page.goto(`${url}/login/?login=${username}&password=${password}`);
|
||||
await page.waitForURL('**/platform/home');
|
||||
await page.waitForTimeout(250);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import { test } from '../baseFixtures.js';
|
||||
import { baseUrl } from '../defaults.js';
|
||||
import { doQuickLogin } from '../login.js';
|
||||
|
||||
const newPartName = 'UITESTIN123';
|
||||
|
||||
test('PUI - Pages - Index - Playground', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
await page.goto('./');
|
||||
// Playground
|
||||
await page.getByRole('tab', { name: 'Playground' }).click();
|
||||
await page.getByRole('button', { name: 'API Forms' }).click();
|
||||
|
||||
// New Part
|
||||
await page.getByRole('button', { name: 'Create New Part' }).click();
|
||||
await page.locator('#react-select-3-input').fill('category 0');
|
||||
await page
|
||||
.getByRole('option', { name: 'Category 0' })
|
||||
.locator('div')
|
||||
.first()
|
||||
.click();
|
||||
await page.getByLabel('Name *').fill(newPartName);
|
||||
await page.getByLabel('Initial Stock Quantity *').fill('1');
|
||||
await page
|
||||
.getByLabel('Create Part')
|
||||
.getByRole('button', { name: 'Cancel' })
|
||||
.click();
|
||||
|
||||
// Edit Part
|
||||
await page.getByRole('button', { name: 'Edit Part' }).click();
|
||||
await page.getByLabel('IPN').click();
|
||||
await page.getByLabel('IPN').fill(newPartName);
|
||||
await page
|
||||
.getByLabel('Edit Part')
|
||||
.getByRole('button', { name: 'Cancel' })
|
||||
.click();
|
||||
|
||||
// Create Stock Item
|
||||
await page.getByRole('button', { name: 'Create Stock Item' }).click();
|
||||
await page.locator('#react-select-25-input').fill('R_1K_0402_1');
|
||||
await page.getByText('R_1K_0402_1%').click();
|
||||
await page
|
||||
.getByLabel('Add Stock Item')
|
||||
.getByRole('button', { name: 'Cancel' })
|
||||
.click();
|
||||
|
||||
// EditCategory
|
||||
await page.getByRole('button', { name: 'Edit Category' }).click();
|
||||
await page.locator('.css-1xvbfjt-Input2').first().click();
|
||||
await page.getByText('Category 0').click();
|
||||
await page
|
||||
.getByLabel('Edit Category')
|
||||
.getByRole('button', { name: 'Cancel' })
|
||||
.click();
|
||||
|
||||
// Create Attachment
|
||||
await page.getByRole('button', { name: 'Create Attachment' }).click();
|
||||
await page.getByLabel('Attachment *').waitFor();
|
||||
await page.getByRole('button', { name: 'Cancel' }).click();
|
||||
// TODO: actually create an attachment
|
||||
|
||||
// Create Part new Modal
|
||||
await page.getByRole('button', { name: 'Create Part new Modal' }).click();
|
||||
await page.locator('.css-1xvbfjt-Input2').first().click();
|
||||
await page.getByText('Category 0').click();
|
||||
await page
|
||||
.getByLabel('Create part')
|
||||
.getByRole('button', { name: 'Cancel' })
|
||||
.click();
|
||||
|
||||
// Status Label
|
||||
await page.getByRole('button', { name: 'Status labels' }).click();
|
||||
await page.getByRole('textbox').dblclick();
|
||||
await page.getByRole('textbox').fill('50');
|
||||
await page.getByText('Attention needed').waitFor();
|
||||
});
|
||||
|
||||
test('PUI - Pages - Index - Dashboard', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
// Dashboard auto update
|
||||
await page.getByRole('tab', { name: 'Dashboard' }).click();
|
||||
await page.getByText('Autoupdate').click();
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByText('Autoupdate').click();
|
||||
await page.getByText('This page is a replacement').waitFor();
|
||||
});
|
||||
@@ -0,0 +1,154 @@
|
||||
import { test } from '@playwright/test';
|
||||
|
||||
import { baseUrl } from '../defaults';
|
||||
import { doQuickLogin } from '../login';
|
||||
|
||||
test('PUI - Pages - Part - Pricing (Nothing, BOM)', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
// Part with no history
|
||||
await page.goto(`${baseUrl}/part/82/pricing`);
|
||||
await page.getByText('1551ABK').waitFor();
|
||||
await page.getByRole('tab', { name: 'Part Pricing' }).click();
|
||||
await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor();
|
||||
await page.getByRole('button', { name: 'Pricing Overview' }).waitFor();
|
||||
await page.getByText('Last Updated').waitFor();
|
||||
await page.getByRole('button', { name: 'Purchase History' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Internal Pricing' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Supplier Pricing' }).isDisabled();
|
||||
|
||||
// Part with history
|
||||
await page.goto(`${baseUrl}/part/108/pricing`);
|
||||
await page.getByText('Part: Blue Chair').waitFor();
|
||||
await page.getByRole('tab', { name: 'Part Pricing' }).click();
|
||||
await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor();
|
||||
await page.getByRole('button', { name: 'Pricing Overview' }).waitFor();
|
||||
await page.getByText('Last Updated').waitFor();
|
||||
await page.getByRole('button', { name: 'Internal Pricing' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Sale History' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Sale Pricing' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'BOM Pricing' }).isEnabled();
|
||||
|
||||
// Overview Graph
|
||||
let graph = page.locator('#pricing-overview-chart');
|
||||
await graph.waitFor();
|
||||
await graph.getByText('$60').waitFor();
|
||||
await graph.getByText('BOM Pricing').waitFor();
|
||||
await graph.getByText('Overall Pricing').waitFor();
|
||||
await graph.locator('path').nth(1).hover();
|
||||
await page.getByText('min_value : $50').waitFor();
|
||||
|
||||
// BOM Pricing
|
||||
await page.getByRole('button', { name: 'BOM Pricing' }).click();
|
||||
await page.getByText('Bar Chart').click();
|
||||
await page.getByText('total_price_min').waitFor();
|
||||
await page.getByText('Pie Chart').click();
|
||||
await page.getByRole('button', { name: 'Quantity Not sorted' }).waitFor();
|
||||
await page.getByRole('button', { name: 'Unit Price Not sorted' }).waitFor();
|
||||
|
||||
// BOM Pricing - linkjumping
|
||||
await page.getByText('Wood Screw').waitFor();
|
||||
await page.getByText('Wood Screw').click();
|
||||
await page.waitForURL('**/part/98/pricing');
|
||||
});
|
||||
|
||||
test('PUI - Pages - Part - Pricing (Supplier)', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
// Part
|
||||
await page.goto(`${baseUrl}/part/55/pricing`);
|
||||
await page.getByText('Part: C_100nF_0603').waitFor();
|
||||
await page.getByRole('tab', { name: 'Part Pricing' }).click();
|
||||
await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor();
|
||||
await page.getByRole('button', { name: 'Pricing Overview' }).waitFor();
|
||||
await page.getByText('Last Updated').waitFor();
|
||||
await page.getByRole('button', { name: 'Purchase History' }).isEnabled();
|
||||
await page.getByRole('button', { name: 'Internal Pricing' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Supplier Pricing' }).isEnabled();
|
||||
|
||||
// Supplier Pricing
|
||||
await page.getByRole('button', { name: 'Supplier Pricing' }).click();
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByRole('button', { name: 'SKU Not sorted' }).waitFor();
|
||||
|
||||
// Supplier Pricing - linkjumping
|
||||
let target = page.getByText('ARR-26041-LPC').first();
|
||||
await target.waitFor();
|
||||
await target.click();
|
||||
// await page.waitForURL('**/purchasing/supplier-part/697/');
|
||||
});
|
||||
|
||||
test('PUI - Pages - Part - Pricing (Variant)', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
// Part
|
||||
await page.goto(`${baseUrl}/part/106/pricing`);
|
||||
await page.getByText('Part: Chair').waitFor();
|
||||
await page.getByRole('tab', { name: 'Part Pricing' }).click();
|
||||
await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor();
|
||||
await page.getByRole('button', { name: 'Pricing Overview' }).waitFor();
|
||||
await page.getByText('Last Updated').waitFor();
|
||||
await page.getByRole('button', { name: 'Internal Pricing' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'BOM Pricing' }).isEnabled();
|
||||
await page.getByRole('button', { name: 'Variant Pricing' }).isEnabled();
|
||||
await page.getByRole('button', { name: 'Sale Pricing' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Sale History' }).isDisabled();
|
||||
|
||||
// Variant Pricing
|
||||
await page.getByRole('button', { name: 'Variant Pricing' }).click();
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByRole('button', { name: 'Variant Part Not sorted' }).click();
|
||||
|
||||
// Variant Pricing - linkjumping
|
||||
let target = page.getByText('Green Chair').first();
|
||||
await target.waitFor();
|
||||
await target.click();
|
||||
await page.waitForURL('**/part/109/pricing');
|
||||
});
|
||||
|
||||
test('PUI - Pages - Part - Pricing (Internal)', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
// Part
|
||||
await page.goto(`${baseUrl}/part/65/pricing`);
|
||||
await page.getByText('Part: M2x4 SHCS').waitFor();
|
||||
await page.getByRole('tab', { name: 'Part Pricing' }).click();
|
||||
await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor();
|
||||
await page.getByRole('button', { name: 'Pricing Overview' }).waitFor();
|
||||
await page.getByText('Last Updated').waitFor();
|
||||
await page.getByRole('button', { name: 'Purchase History' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Internal Pricing' }).isEnabled();
|
||||
await page.getByRole('button', { name: 'Supplier Pricing' }).isDisabled();
|
||||
|
||||
// Internal Pricing
|
||||
await page.getByRole('button', { name: 'Internal Pricing' }).click();
|
||||
await page.getByRole('button', { name: 'Price Break Not sorted' }).waitFor();
|
||||
|
||||
// Internal Pricing - editing
|
||||
await page.getByRole('row', { name: '1 NZ$' }).getByRole('button').click();
|
||||
await page.getByRole('menuitem', { name: 'Edit' }).click();
|
||||
await page.getByText('Part *M2x4 SHCSSocket head').click();
|
||||
await page.getByText('Part *M2x4 SHCSSocket head').click();
|
||||
});
|
||||
|
||||
test('PUI - Pages - Part - Pricing (Purchase)', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
// Part
|
||||
await page.goto(`${baseUrl}/part/69/pricing`);
|
||||
await page.getByText('Part: 530470210').waitFor();
|
||||
await page.getByRole('tab', { name: 'Part Pricing' }).click();
|
||||
await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor();
|
||||
await page.getByRole('button', { name: 'Pricing Overview' }).waitFor();
|
||||
await page.getByText('Last Updated').waitFor();
|
||||
await page.getByRole('button', { name: 'Purchase History' }).isEnabled();
|
||||
await page.getByRole('button', { name: 'Internal Pricing' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Supplier Pricing' }).isDisabled();
|
||||
|
||||
// Purchase History
|
||||
await page.getByRole('button', { name: 'Purchase History' }).click();
|
||||
await page
|
||||
.getByRole('button', { name: 'Purchase Order Not sorted' })
|
||||
.waitFor();
|
||||
await page.getByText('2022-04-29').waitFor();
|
||||
});
|
||||
Reference in New Issue
Block a user