mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge remote-tracking branch 'inventree/master'
This commit is contained in:
commit
aba7e53916
1
.github/workflows/translations.yml
vendored
1
.github/workflows/translations.yml
vendored
@ -46,3 +46,4 @@ jobs:
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: l10
|
||||
force: true
|
||||
|
@ -44,6 +44,31 @@ The HEAD of the "stable" branch represents the latest stable release code.
|
||||
- When approved, the branch is merged back *into* stable, with an incremented PATCH number (e.g. 0.4.1 -> 0.4.2)
|
||||
- The bugfix *must* also be cherry picked into the *master* branch.
|
||||
|
||||
## Environment
|
||||
#### Target version
|
||||
We are currently targeting:
|
||||
| Name | Minimum version |
|
||||
|---|---|
|
||||
| Python | 3.9 |
|
||||
| Django | 3.2 |
|
||||
|
||||
### Auto creating updates
|
||||
The following tools can be used to auto-upgrade syntax that was depreciated in new versions:
|
||||
```bash
|
||||
pip install pyupgrade
|
||||
pip install django-upgrade
|
||||
```
|
||||
|
||||
To update the codebase run the following script.
|
||||
```bash
|
||||
pyupgrade `find . -name "*.py"`
|
||||
django-upgrade --target-version 3.2 `find . -name "*.py"`
|
||||
```
|
||||
|
||||
### Credits
|
||||
If you add any new dependencies / libraries, they need to be added to [the docs](https://github.com/inventree/inventree-docs/blob/master/docs/credits.md). Please try to do that as timely as possible.
|
||||
|
||||
|
||||
## Migration Files
|
||||
|
||||
Any required migration files **must** be included in the commit, or the pull-request will be rejected. If you change the underlying database schema, make sure you run `invoke migrate` and commit the migration files before submitting the PR.
|
||||
|
@ -5,7 +5,7 @@ Main JSON interface views
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.conf import settings
|
||||
from django.http import JsonResponse
|
||||
|
||||
|
@ -6,7 +6,7 @@ import sys
|
||||
|
||||
from .validators import allowable_url_schemes
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from django.forms.fields import URLField as FormURLField
|
||||
from django.db import models as models
|
||||
|
@ -7,7 +7,7 @@ from __future__ import unicode_literals
|
||||
from urllib.parse import urlencode
|
||||
import logging
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django import forms
|
||||
from django.contrib.auth.models import User, Group
|
||||
from django.conf import settings
|
||||
@ -319,7 +319,7 @@ class CustomSocialAccountAdapter(RegistratonMixin, DefaultSocialAccountAdapter):
|
||||
redirect_url = reverse('two-factor-authenticate')
|
||||
# Add GET parameters to the URL if they exist.
|
||||
if request.GET:
|
||||
redirect_url += u'?' + urlencode(request.GET)
|
||||
redirect_url += '?' + urlencode(request.GET)
|
||||
|
||||
raise ImmediateHttpResponse(
|
||||
response=HttpResponseRedirect(redirect_url)
|
||||
|
@ -13,7 +13,7 @@ from decimal import Decimal, InvalidOperation
|
||||
from wsgiref.util import FileWrapper
|
||||
from django.http import StreamingHttpResponse
|
||||
from django.core.exceptions import ValidationError, FieldError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
|
||||
@ -432,7 +432,7 @@ def extract_serial_numbers(serials, expected_quantity, next_number: int):
|
||||
next_number += 1
|
||||
|
||||
# Split input string by whitespace or comma (,) characters
|
||||
groups = re.split("[\s,]+", serials)
|
||||
groups = re.split(r"[\s,]+", serials)
|
||||
|
||||
numbers = []
|
||||
errors = []
|
||||
|
@ -1,7 +1,7 @@
|
||||
from django.shortcuts import HttpResponseRedirect
|
||||
from django.urls import reverse_lazy, Resolver404
|
||||
from django.shortcuts import redirect
|
||||
from django.conf.urls import include, url
|
||||
from django.urls import include, re_path
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.middleware import PersistentRemoteUserMiddleware
|
||||
|
||||
@ -85,14 +85,14 @@ class AuthRequiredMiddleware(object):
|
||||
if path not in urls and not path.startswith('/api/'):
|
||||
# Save the 'next' parameter to pass through to the login view
|
||||
|
||||
return redirect('%s?next=%s' % (reverse_lazy('account_login'), request.path))
|
||||
return redirect('{}?next={}'.format(reverse_lazy('account_login'), request.path))
|
||||
|
||||
response = self.get_response(request)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
url_matcher = url('', include(frontendpatterns))
|
||||
url_matcher = re_path('', include(frontendpatterns))
|
||||
|
||||
|
||||
class Check2FAMiddleware(BaseRequire2FAMiddleware):
|
||||
|
@ -15,7 +15,7 @@ from collections import OrderedDict
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import ValidationError as DjangoValidationError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.db import models
|
||||
|
||||
from djmoney.contrib.django_rest_framework.fields import MoneyField
|
||||
|
@ -3,7 +3,7 @@ Provides system status functionality checks.
|
||||
"""
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils import timezone
|
||||
|
||||
import logging
|
||||
|
@ -1,4 +1,4 @@
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class StatusCode:
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import json
|
||||
from test.support import EnvironmentVarGuard
|
||||
|
||||
@ -186,7 +185,7 @@ class TestDownloadFile(TestCase):
|
||||
|
||||
def test_download(self):
|
||||
helpers.DownloadFile("hello world", "out.txt")
|
||||
helpers.DownloadFile(bytes("hello world".encode("utf8")), "out.bin")
|
||||
helpers.DownloadFile(bytes(b"hello world"), "out.bin")
|
||||
|
||||
|
||||
class TestMPTT(TestCase):
|
||||
|
@ -4,8 +4,7 @@ Top-level URL lookup for InvenTree application.
|
||||
Passes URL lookup downstream to each app as required.
|
||||
"""
|
||||
|
||||
from django.conf.urls import url, include
|
||||
from django.urls import path
|
||||
from django.urls import include, path, re_path
|
||||
from django.contrib import admin
|
||||
|
||||
from company.urls import company_urls
|
||||
@ -56,144 +55,144 @@ apipatterns = []
|
||||
|
||||
if settings.PLUGINS_ENABLED:
|
||||
apipatterns.append(
|
||||
url(r'^plugin/', include(plugin_api_urls))
|
||||
re_path(r'^plugin/', include(plugin_api_urls))
|
||||
)
|
||||
|
||||
apipatterns += [
|
||||
url(r'^barcode/', include(barcode_api_urls)),
|
||||
url(r'^settings/', include(settings_api_urls)),
|
||||
url(r'^part/', include(part_api_urls)),
|
||||
url(r'^bom/', include(bom_api_urls)),
|
||||
url(r'^company/', include(company_api_urls)),
|
||||
url(r'^stock/', include(stock_api_urls)),
|
||||
url(r'^build/', include(build_api_urls)),
|
||||
url(r'^order/', include(order_api_urls)),
|
||||
url(r'^label/', include(label_api_urls)),
|
||||
url(r'^report/', include(report_api_urls)),
|
||||
re_path(r'^barcode/', include(barcode_api_urls)),
|
||||
re_path(r'^settings/', include(settings_api_urls)),
|
||||
re_path(r'^part/', include(part_api_urls)),
|
||||
re_path(r'^bom/', include(bom_api_urls)),
|
||||
re_path(r'^company/', include(company_api_urls)),
|
||||
re_path(r'^stock/', include(stock_api_urls)),
|
||||
re_path(r'^build/', include(build_api_urls)),
|
||||
re_path(r'^order/', include(order_api_urls)),
|
||||
re_path(r'^label/', include(label_api_urls)),
|
||||
re_path(r'^report/', include(report_api_urls)),
|
||||
|
||||
# User URLs
|
||||
url(r'^user/', include(user_urls)),
|
||||
re_path(r'^user/', include(user_urls)),
|
||||
|
||||
# Plugin endpoints
|
||||
url(r'^action/', ActionPluginView.as_view(), name='api-action-plugin'),
|
||||
re_path(r'^action/', ActionPluginView.as_view(), name='api-action-plugin'),
|
||||
|
||||
# Webhook enpoint
|
||||
path('', include(common_api_urls)),
|
||||
|
||||
# InvenTree information endpoint
|
||||
url(r'^$', InfoView.as_view(), name='api-inventree-info'),
|
||||
path('', InfoView.as_view(), name='api-inventree-info'),
|
||||
|
||||
# Unknown endpoint
|
||||
url(r'^.*$', NotFoundView.as_view(), name='api-404'),
|
||||
re_path(r'^.*$', NotFoundView.as_view(), name='api-404'),
|
||||
]
|
||||
|
||||
settings_urls = [
|
||||
|
||||
url(r'^i18n/?', include('django.conf.urls.i18n')),
|
||||
re_path(r'^i18n/?', include('django.conf.urls.i18n')),
|
||||
|
||||
url(r'^appearance/?', AppearanceSelectView.as_view(), name='settings-appearance'),
|
||||
url(r'^currencies-refresh/', CurrencyRefreshView.as_view(), name='settings-currencies-refresh'),
|
||||
re_path(r'^appearance/?', AppearanceSelectView.as_view(), name='settings-appearance'),
|
||||
re_path(r'^currencies-refresh/', CurrencyRefreshView.as_view(), name='settings-currencies-refresh'),
|
||||
|
||||
url(r'^category/', SettingCategorySelectView.as_view(), name='settings-category'),
|
||||
re_path(r'^category/', SettingCategorySelectView.as_view(), name='settings-category'),
|
||||
|
||||
# Catch any other urls
|
||||
url(r'^.*$', SettingsView.as_view(template_name='InvenTree/settings/settings.html'), name='settings'),
|
||||
re_path(r'^.*$', SettingsView.as_view(template_name='InvenTree/settings/settings.html'), name='settings'),
|
||||
]
|
||||
|
||||
notifications_urls = [
|
||||
|
||||
# Catch any other urls
|
||||
url(r'^.*$', NotificationsView.as_view(), name='notifications'),
|
||||
re_path(r'^.*$', NotificationsView.as_view(), name='notifications'),
|
||||
]
|
||||
|
||||
# These javascript files are served "dynamically" - i.e. rendered on demand
|
||||
dynamic_javascript_urls = [
|
||||
url(r'^calendar.js', DynamicJsView.as_view(template_name='js/dynamic/calendar.js'), name='calendar.js'),
|
||||
url(r'^nav.js', DynamicJsView.as_view(template_name='js/dynamic/nav.js'), name='nav.js'),
|
||||
url(r'^settings.js', DynamicJsView.as_view(template_name='js/dynamic/settings.js'), name='settings.js'),
|
||||
re_path(r'^calendar.js', DynamicJsView.as_view(template_name='js/dynamic/calendar.js'), name='calendar.js'),
|
||||
re_path(r'^nav.js', DynamicJsView.as_view(template_name='js/dynamic/nav.js'), name='nav.js'),
|
||||
re_path(r'^settings.js', DynamicJsView.as_view(template_name='js/dynamic/settings.js'), name='settings.js'),
|
||||
]
|
||||
|
||||
# These javascript files are pased through the Django translation layer
|
||||
translated_javascript_urls = [
|
||||
url(r'^api.js', DynamicJsView.as_view(template_name='js/translated/api.js'), name='api.js'),
|
||||
url(r'^attachment.js', DynamicJsView.as_view(template_name='js/translated/attachment.js'), name='attachment.js'),
|
||||
url(r'^barcode.js', DynamicJsView.as_view(template_name='js/translated/barcode.js'), name='barcode.js'),
|
||||
url(r'^bom.js', DynamicJsView.as_view(template_name='js/translated/bom.js'), name='bom.js'),
|
||||
url(r'^build.js', DynamicJsView.as_view(template_name='js/translated/build.js'), name='build.js'),
|
||||
url(r'^company.js', DynamicJsView.as_view(template_name='js/translated/company.js'), name='company.js'),
|
||||
url(r'^filters.js', DynamicJsView.as_view(template_name='js/translated/filters.js'), name='filters.js'),
|
||||
url(r'^forms.js', DynamicJsView.as_view(template_name='js/translated/forms.js'), name='forms.js'),
|
||||
url(r'^helpers.js', DynamicJsView.as_view(template_name='js/translated/helpers.js'), name='helpers.js'),
|
||||
url(r'^label.js', DynamicJsView.as_view(template_name='js/translated/label.js'), name='label.js'),
|
||||
url(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/translated/model_renderers.js'), name='model_renderers.js'),
|
||||
url(r'^modals.js', DynamicJsView.as_view(template_name='js/translated/modals.js'), name='modals.js'),
|
||||
url(r'^order.js', DynamicJsView.as_view(template_name='js/translated/order.js'), name='order.js'),
|
||||
url(r'^part.js', DynamicJsView.as_view(template_name='js/translated/part.js'), name='part.js'),
|
||||
url(r'^report.js', DynamicJsView.as_view(template_name='js/translated/report.js'), name='report.js'),
|
||||
url(r'^search.js', DynamicJsView.as_view(template_name='js/translated/search.js'), name='search.js'),
|
||||
url(r'^stock.js', DynamicJsView.as_view(template_name='js/translated/stock.js'), name='stock.js'),
|
||||
url(r'^plugin.js', DynamicJsView.as_view(template_name='js/translated/plugin.js'), name='plugin.js'),
|
||||
url(r'^tables.js', DynamicJsView.as_view(template_name='js/translated/tables.js'), name='tables.js'),
|
||||
url(r'^table_filters.js', DynamicJsView.as_view(template_name='js/translated/table_filters.js'), name='table_filters.js'),
|
||||
url(r'^notification.js', DynamicJsView.as_view(template_name='js/translated/notification.js'), name='notification.js'),
|
||||
re_path(r'^api.js', DynamicJsView.as_view(template_name='js/translated/api.js'), name='api.js'),
|
||||
re_path(r'^attachment.js', DynamicJsView.as_view(template_name='js/translated/attachment.js'), name='attachment.js'),
|
||||
re_path(r'^barcode.js', DynamicJsView.as_view(template_name='js/translated/barcode.js'), name='barcode.js'),
|
||||
re_path(r'^bom.js', DynamicJsView.as_view(template_name='js/translated/bom.js'), name='bom.js'),
|
||||
re_path(r'^build.js', DynamicJsView.as_view(template_name='js/translated/build.js'), name='build.js'),
|
||||
re_path(r'^company.js', DynamicJsView.as_view(template_name='js/translated/company.js'), name='company.js'),
|
||||
re_path(r'^filters.js', DynamicJsView.as_view(template_name='js/translated/filters.js'), name='filters.js'),
|
||||
re_path(r'^forms.js', DynamicJsView.as_view(template_name='js/translated/forms.js'), name='forms.js'),
|
||||
re_path(r'^helpers.js', DynamicJsView.as_view(template_name='js/translated/helpers.js'), name='helpers.js'),
|
||||
re_path(r'^label.js', DynamicJsView.as_view(template_name='js/translated/label.js'), name='label.js'),
|
||||
re_path(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/translated/model_renderers.js'), name='model_renderers.js'),
|
||||
re_path(r'^modals.js', DynamicJsView.as_view(template_name='js/translated/modals.js'), name='modals.js'),
|
||||
re_path(r'^order.js', DynamicJsView.as_view(template_name='js/translated/order.js'), name='order.js'),
|
||||
re_path(r'^part.js', DynamicJsView.as_view(template_name='js/translated/part.js'), name='part.js'),
|
||||
re_path(r'^report.js', DynamicJsView.as_view(template_name='js/translated/report.js'), name='report.js'),
|
||||
re_path(r'^search.js', DynamicJsView.as_view(template_name='js/translated/search.js'), name='search.js'),
|
||||
re_path(r'^stock.js', DynamicJsView.as_view(template_name='js/translated/stock.js'), name='stock.js'),
|
||||
re_path(r'^plugin.js', DynamicJsView.as_view(template_name='js/translated/plugin.js'), name='plugin.js'),
|
||||
re_path(r'^tables.js', DynamicJsView.as_view(template_name='js/translated/tables.js'), name='tables.js'),
|
||||
re_path(r'^table_filters.js', DynamicJsView.as_view(template_name='js/translated/table_filters.js'), name='table_filters.js'),
|
||||
re_path(r'^notification.js', DynamicJsView.as_view(template_name='js/translated/notification.js'), name='notification.js'),
|
||||
]
|
||||
|
||||
backendpatterns = [
|
||||
# "Dynamic" javascript files which are rendered using InvenTree templating.
|
||||
url(r'^js/dynamic/', include(dynamic_javascript_urls)),
|
||||
url(r'^js/i18n/', include(translated_javascript_urls)),
|
||||
re_path(r'^js/dynamic/', include(dynamic_javascript_urls)),
|
||||
re_path(r'^js/i18n/', include(translated_javascript_urls)),
|
||||
|
||||
url(r'^auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||
url(r'^auth/?', auth_request),
|
||||
re_path(r'^auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||
re_path(r'^auth/?', auth_request),
|
||||
|
||||
url(r'^api/', include(apipatterns)),
|
||||
url(r'^api-doc/', include_docs_urls(title='InvenTree API')),
|
||||
re_path(r'^api/', include(apipatterns)),
|
||||
re_path(r'^api-doc/', include_docs_urls(title='InvenTree API')),
|
||||
|
||||
# 3rd party endpoints
|
||||
url(r'^markdownx/', include('markdownx.urls')),
|
||||
re_path(r'^markdownx/', include('markdownx.urls')),
|
||||
]
|
||||
|
||||
frontendpatterns = [
|
||||
url(r'^part/', include(part_urls)),
|
||||
url(r'^manufacturer-part/', include(manufacturer_part_urls)),
|
||||
url(r'^supplier-part/', include(supplier_part_urls)),
|
||||
re_path(r'^part/', include(part_urls)),
|
||||
re_path(r'^manufacturer-part/', include(manufacturer_part_urls)),
|
||||
re_path(r'^supplier-part/', include(supplier_part_urls)),
|
||||
|
||||
url(r'^common/', include(common_urls)),
|
||||
re_path(r'^common/', include(common_urls)),
|
||||
|
||||
url(r'^stock/', include(stock_urls)),
|
||||
re_path(r'^stock/', include(stock_urls)),
|
||||
|
||||
url(r'^company/', include(company_urls)),
|
||||
url(r'^order/', include(order_urls)),
|
||||
re_path(r'^company/', include(company_urls)),
|
||||
re_path(r'^order/', include(order_urls)),
|
||||
|
||||
url(r'^build/', include(build_urls)),
|
||||
re_path(r'^build/', include(build_urls)),
|
||||
|
||||
url(r'^settings/', include(settings_urls)),
|
||||
re_path(r'^settings/', include(settings_urls)),
|
||||
|
||||
url(r'^notifications/', include(notifications_urls)),
|
||||
re_path(r'^notifications/', include(notifications_urls)),
|
||||
|
||||
url(r'^edit-user/', EditUserView.as_view(), name='edit-user'),
|
||||
url(r'^set-password/', SetPasswordView.as_view(), name='set-password'),
|
||||
re_path(r'^edit-user/', EditUserView.as_view(), name='edit-user'),
|
||||
re_path(r'^set-password/', SetPasswordView.as_view(), name='set-password'),
|
||||
|
||||
url(r'^index/', IndexView.as_view(), name='index'),
|
||||
url(r'^search/', SearchView.as_view(), name='search'),
|
||||
url(r'^stats/', DatabaseStatsView.as_view(), name='stats'),
|
||||
re_path(r'^index/', IndexView.as_view(), name='index'),
|
||||
re_path(r'^search/', SearchView.as_view(), name='search'),
|
||||
re_path(r'^stats/', DatabaseStatsView.as_view(), name='stats'),
|
||||
|
||||
# admin sites
|
||||
url(f'^{settings.INVENTREE_ADMIN_URL}/error_log/', include('error_report.urls')),
|
||||
url(f'^{settings.INVENTREE_ADMIN_URL}/shell/', include('django_admin_shell.urls')),
|
||||
url(f'^{settings.INVENTREE_ADMIN_URL}/', admin.site.urls, name='inventree-admin'),
|
||||
re_path(f'^{settings.INVENTREE_ADMIN_URL}/error_log/', include('error_report.urls')),
|
||||
re_path(f'^{settings.INVENTREE_ADMIN_URL}/shell/', include('django_admin_shell.urls')),
|
||||
re_path(f'^{settings.INVENTREE_ADMIN_URL}/', admin.site.urls, name='inventree-admin'),
|
||||
|
||||
# DB user sessions
|
||||
url(r'^accounts/sessions/other/delete/$', view=CustomSessionDeleteOtherView.as_view(), name='session_delete_other', ),
|
||||
url(r'^accounts/sessions/(?P<pk>\w+)/delete/$', view=CustomSessionDeleteView.as_view(), name='session_delete', ),
|
||||
path('accounts/sessions/other/delete/', view=CustomSessionDeleteOtherView.as_view(), name='session_delete_other', ),
|
||||
re_path(r'^accounts/sessions/(?P<pk>\w+)/delete/$', view=CustomSessionDeleteView.as_view(), name='session_delete', ),
|
||||
|
||||
# Single Sign On / allauth
|
||||
# overrides of urlpatterns
|
||||
url(r'^accounts/email/', CustomEmailView.as_view(), name='account_email'),
|
||||
url(r'^accounts/social/connections/', CustomConnectionsView.as_view(), name='socialaccount_connections'),
|
||||
url(r"^accounts/password/reset/key/(?P<uidb36>[0-9A-Za-z]+)-(?P<key>.+)/$", CustomPasswordResetFromKeyView.as_view(), name="account_reset_password_from_key"),
|
||||
url(r'^accounts/', include('allauth_2fa.urls')), # MFA support
|
||||
url(r'^accounts/', include('allauth.urls')), # included urlpatterns
|
||||
re_path(r'^accounts/email/', CustomEmailView.as_view(), name='account_email'),
|
||||
re_path(r'^accounts/social/connections/', CustomConnectionsView.as_view(), name='socialaccount_connections'),
|
||||
re_path(r"^accounts/password/reset/key/(?P<uidb36>[0-9A-Za-z]+)-(?P<key>.+)/$", CustomPasswordResetFromKeyView.as_view(), name="account_reset_password_from_key"),
|
||||
re_path(r'^accounts/', include('allauth_2fa.urls')), # MFA support
|
||||
re_path(r'^accounts/', include('allauth.urls')), # included urlpatterns
|
||||
]
|
||||
|
||||
# Append custom plugin URLs (if plugin support is enabled)
|
||||
@ -201,8 +200,8 @@ if settings.PLUGINS_ENABLED:
|
||||
frontendpatterns.append(get_plugin_urls())
|
||||
|
||||
urlpatterns = [
|
||||
url('', include(frontendpatterns)),
|
||||
url('', include(backendpatterns)),
|
||||
re_path('', include(frontendpatterns)),
|
||||
re_path('', include(backendpatterns)),
|
||||
]
|
||||
|
||||
# Server running in "DEBUG" mode?
|
||||
@ -221,4 +220,4 @@ if settings.DEBUG:
|
||||
] + urlpatterns
|
||||
|
||||
# Send any unknown URLs to the parts page
|
||||
urlpatterns += [url(r'^.*$', RedirectView.as_view(url='/index/', permanent=False), name='index')]
|
||||
urlpatterns += [re_path(r'^.*$', RedirectView.as_view(url='/index/', permanent=False), name='index')]
|
||||
|
@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.urls import reverse
|
||||
from django.conf.urls import url
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.urls import path, re_path
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from rest_framework import permissions
|
||||
@ -240,8 +240,8 @@ class BarcodeAssign(APIView):
|
||||
|
||||
barcode_api_urls = [
|
||||
|
||||
url(r'^link/$', BarcodeAssign.as_view(), name='api-barcode-link'),
|
||||
path('link/', BarcodeAssign.as_view(), name='api-barcode-link'),
|
||||
|
||||
# Catch-all performs barcode 'scan'
|
||||
url(r'^.*$', BarcodeScan.as_view(), name='api-barcode-scan'),
|
||||
re_path(r'^.*$', BarcodeScan.as_view(), name='api-barcode-scan'),
|
||||
]
|
||||
|
@ -5,7 +5,7 @@ JSON API for the Build app
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf.urls import url, include
|
||||
from django.urls import include, re_path
|
||||
|
||||
from rest_framework import filters, generics
|
||||
|
||||
@ -508,29 +508,29 @@ class BuildAttachmentDetail(generics.RetrieveUpdateDestroyAPIView, AttachmentMix
|
||||
build_api_urls = [
|
||||
|
||||
# Attachments
|
||||
url(r'^attachment/', include([
|
||||
url(r'^(?P<pk>\d+)/', BuildAttachmentDetail.as_view(), name='api-build-attachment-detail'),
|
||||
url(r'^.*$', BuildAttachmentList.as_view(), name='api-build-attachment-list'),
|
||||
re_path(r'^attachment/', include([
|
||||
re_path(r'^(?P<pk>\d+)/', BuildAttachmentDetail.as_view(), name='api-build-attachment-detail'),
|
||||
re_path(r'^.*$', BuildAttachmentList.as_view(), name='api-build-attachment-list'),
|
||||
])),
|
||||
|
||||
# Build Items
|
||||
url(r'^item/', include([
|
||||
url(r'^(?P<pk>\d+)/', BuildItemDetail.as_view(), name='api-build-item-detail'),
|
||||
url(r'^.*$', BuildItemList.as_view(), name='api-build-item-list'),
|
||||
re_path(r'^item/', include([
|
||||
re_path(r'^(?P<pk>\d+)/', BuildItemDetail.as_view(), name='api-build-item-detail'),
|
||||
re_path(r'^.*$', BuildItemList.as_view(), name='api-build-item-list'),
|
||||
])),
|
||||
|
||||
# Build Detail
|
||||
url(r'^(?P<pk>\d+)/', include([
|
||||
url(r'^allocate/', BuildAllocate.as_view(), name='api-build-allocate'),
|
||||
url(r'^auto-allocate/', BuildAutoAllocate.as_view(), name='api-build-auto-allocate'),
|
||||
url(r'^complete/', BuildOutputComplete.as_view(), name='api-build-output-complete'),
|
||||
url(r'^create-output/', BuildOutputCreate.as_view(), name='api-build-output-create'),
|
||||
url(r'^delete-outputs/', BuildOutputDelete.as_view(), name='api-build-output-delete'),
|
||||
url(r'^finish/', BuildFinish.as_view(), name='api-build-finish'),
|
||||
url(r'^unallocate/', BuildUnallocate.as_view(), name='api-build-unallocate'),
|
||||
url(r'^.*$', BuildDetail.as_view(), name='api-build-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
re_path(r'^allocate/', BuildAllocate.as_view(), name='api-build-allocate'),
|
||||
re_path(r'^auto-allocate/', BuildAutoAllocate.as_view(), name='api-build-auto-allocate'),
|
||||
re_path(r'^complete/', BuildOutputComplete.as_view(), name='api-build-output-complete'),
|
||||
re_path(r'^create-output/', BuildOutputCreate.as_view(), name='api-build-output-create'),
|
||||
re_path(r'^delete-outputs/', BuildOutputDelete.as_view(), name='api-build-output-delete'),
|
||||
re_path(r'^finish/', BuildFinish.as_view(), name='api-build-finish'),
|
||||
re_path(r'^unallocate/', BuildUnallocate.as_view(), name='api-build-unallocate'),
|
||||
re_path(r'^.*$', BuildDetail.as_view(), name='api-build-detail'),
|
||||
])),
|
||||
|
||||
# Build List
|
||||
url(r'^.*$', BuildList.as_view(), name='api-build-list'),
|
||||
re_path(r'^.*$', BuildList.as_view(), name='api-build-list'),
|
||||
]
|
||||
|
@ -6,7 +6,7 @@ Django Forms for interacting with Build objects
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django import forms
|
||||
|
||||
from InvenTree.forms import HelperForm
|
||||
|
@ -18,7 +18,7 @@ from django.db.models.functions import Coalesce
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch.dispatcher import receiver
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from markdownx.models import MarkdownxField
|
||||
|
||||
@ -53,7 +53,7 @@ def get_next_build_number():
|
||||
|
||||
build = Build.objects.exclude(reference=None).last()
|
||||
|
||||
attempts = set([build.reference])
|
||||
attempts = {build.reference}
|
||||
|
||||
reference = build.reference
|
||||
|
||||
|
@ -7,7 +7,7 @@ from __future__ import unicode_literals
|
||||
|
||||
from django.db import transaction
|
||||
from django.core.exceptions import ValidationError as DjangoValidationError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from django.db.models import Case, When, Value
|
||||
from django.db.models import BooleanField
|
||||
|
@ -4,7 +4,7 @@ from __future__ import unicode_literals
|
||||
from decimal import Decimal
|
||||
import logging
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
from allauth.account.models import EmailAddress
|
||||
|
@ -2,20 +2,20 @@
|
||||
URL lookup for Build app
|
||||
"""
|
||||
|
||||
from django.conf.urls import url, include
|
||||
from django.urls import include, re_path
|
||||
|
||||
from . import views
|
||||
|
||||
build_detail_urls = [
|
||||
url(r'^cancel/', views.BuildCancel.as_view(), name='build-cancel'),
|
||||
url(r'^delete/', views.BuildDelete.as_view(), name='build-delete'),
|
||||
re_path(r'^cancel/', views.BuildCancel.as_view(), name='build-cancel'),
|
||||
re_path(r'^delete/', views.BuildDelete.as_view(), name='build-delete'),
|
||||
|
||||
url(r'^.*$', views.BuildDetail.as_view(), name='build-detail'),
|
||||
re_path(r'^.*$', views.BuildDetail.as_view(), name='build-detail'),
|
||||
]
|
||||
|
||||
build_urls = [
|
||||
|
||||
url(r'^(?P<pk>\d+)/', include(build_detail_urls)),
|
||||
re_path(r'^(?P<pk>\d+)/', include(build_detail_urls)),
|
||||
|
||||
url(r'.*$', views.BuildIndex.as_view(), name='build-index'),
|
||||
re_path(r'.*$', views.BuildIndex.as_view(), name='build-index'),
|
||||
]
|
||||
|
@ -5,7 +5,7 @@ Django views for interacting with Build objects
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import DetailView, ListView
|
||||
|
||||
from .models import Build
|
||||
|
@ -11,7 +11,7 @@ from django.http.response import HttpResponse
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.urls import path
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.conf.urls import url, include
|
||||
from django.urls import include, re_path
|
||||
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
@ -336,21 +336,21 @@ class NotificationReadAll(generics.RetrieveAPIView):
|
||||
|
||||
settings_api_urls = [
|
||||
# User settings
|
||||
url(r'^user/', include([
|
||||
re_path(r'^user/', include([
|
||||
# User Settings Detail
|
||||
url(r'^(?P<pk>\d+)/', UserSettingsDetail.as_view(), name='api-user-setting-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/', UserSettingsDetail.as_view(), name='api-user-setting-detail'),
|
||||
|
||||
# User Settings List
|
||||
url(r'^.*$', UserSettingsList.as_view(), name='api-user-setting-list'),
|
||||
re_path(r'^.*$', UserSettingsList.as_view(), name='api-user-setting-list'),
|
||||
])),
|
||||
|
||||
# Global settings
|
||||
url(r'^global/', include([
|
||||
re_path(r'^global/', include([
|
||||
# Global Settings Detail
|
||||
url(r'^(?P<pk>\d+)/', GlobalSettingsDetail.as_view(), name='api-global-setting-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/', GlobalSettingsDetail.as_view(), name='api-global-setting-detail'),
|
||||
|
||||
# Global Settings List
|
||||
url(r'^.*$', GlobalSettingsList.as_view(), name='api-global-setting-list'),
|
||||
re_path(r'^.*$', GlobalSettingsList.as_view(), name='api-global-setting-list'),
|
||||
])),
|
||||
]
|
||||
|
||||
@ -359,18 +359,18 @@ common_api_urls = [
|
||||
path('webhook/<slug:endpoint>/', WebhookView.as_view(), name='api-webhook'),
|
||||
|
||||
# Notifications
|
||||
url(r'^notifications/', include([
|
||||
re_path(r'^notifications/', include([
|
||||
# Individual purchase order detail URLs
|
||||
url(r'^(?P<pk>\d+)/', include([
|
||||
url(r'^read/', NotificationRead.as_view(), name='api-notifications-read'),
|
||||
url(r'^unread/', NotificationUnread.as_view(), name='api-notifications-unread'),
|
||||
url(r'.*$', NotificationDetail.as_view(), name='api-notifications-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
re_path(r'^read/', NotificationRead.as_view(), name='api-notifications-read'),
|
||||
re_path(r'^unread/', NotificationUnread.as_view(), name='api-notifications-unread'),
|
||||
re_path(r'.*$', NotificationDetail.as_view(), name='api-notifications-detail'),
|
||||
])),
|
||||
# Read all
|
||||
url(r'^readall/', NotificationReadAll.as_view(), name='api-notifications-readall'),
|
||||
re_path(r'^readall/', NotificationReadAll.as_view(), name='api-notifications-readall'),
|
||||
|
||||
# Notification messages list
|
||||
url(r'^.*$', NotificationList.as_view(), name='api-notifications-list'),
|
||||
re_path(r'^.*$', NotificationList.as_view(), name='api-notifications-list'),
|
||||
])),
|
||||
|
||||
]
|
||||
|
@ -33,7 +33,7 @@ from djmoney.contrib.exchange.exceptions import MissingRate
|
||||
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.core.validators import MinValueValidator, URLValidator
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
from django.test import TestCase
|
||||
|
||||
|
@ -7,7 +7,7 @@ from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.conf import settings
|
||||
from django.core.files.storage import FileSystemStorage
|
||||
|
||||
|
@ -11,7 +11,7 @@ from django_filters import rest_framework as rest_filters
|
||||
from rest_framework import filters
|
||||
from rest_framework import generics
|
||||
|
||||
from django.conf.urls import url, include
|
||||
from django.urls import include, re_path
|
||||
from django.db.models import Q
|
||||
|
||||
from InvenTree.helpers import str2bool
|
||||
@ -390,42 +390,42 @@ class SupplierPriceBreakDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||
|
||||
manufacturer_part_api_urls = [
|
||||
|
||||
url(r'^parameter/', include([
|
||||
url(r'^(?P<pk>\d+)/', ManufacturerPartParameterDetail.as_view(), name='api-manufacturer-part-parameter-detail'),
|
||||
re_path(r'^parameter/', include([
|
||||
re_path(r'^(?P<pk>\d+)/', ManufacturerPartParameterDetail.as_view(), name='api-manufacturer-part-parameter-detail'),
|
||||
|
||||
# Catch anything else
|
||||
url(r'^.*$', ManufacturerPartParameterList.as_view(), name='api-manufacturer-part-parameter-list'),
|
||||
re_path(r'^.*$', ManufacturerPartParameterList.as_view(), name='api-manufacturer-part-parameter-list'),
|
||||
])),
|
||||
|
||||
url(r'^(?P<pk>\d+)/?', ManufacturerPartDetail.as_view(), name='api-manufacturer-part-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/?', ManufacturerPartDetail.as_view(), name='api-manufacturer-part-detail'),
|
||||
|
||||
# Catch anything else
|
||||
url(r'^.*$', ManufacturerPartList.as_view(), name='api-manufacturer-part-list'),
|
||||
re_path(r'^.*$', ManufacturerPartList.as_view(), name='api-manufacturer-part-list'),
|
||||
]
|
||||
|
||||
|
||||
supplier_part_api_urls = [
|
||||
|
||||
url(r'^(?P<pk>\d+)/?', SupplierPartDetail.as_view(), name='api-supplier-part-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/?', SupplierPartDetail.as_view(), name='api-supplier-part-detail'),
|
||||
|
||||
# Catch anything else
|
||||
url(r'^.*$', SupplierPartList.as_view(), name='api-supplier-part-list'),
|
||||
re_path(r'^.*$', SupplierPartList.as_view(), name='api-supplier-part-list'),
|
||||
]
|
||||
|
||||
|
||||
company_api_urls = [
|
||||
url(r'^part/manufacturer/', include(manufacturer_part_api_urls)),
|
||||
re_path(r'^part/manufacturer/', include(manufacturer_part_api_urls)),
|
||||
|
||||
url(r'^part/', include(supplier_part_api_urls)),
|
||||
re_path(r'^part/', include(supplier_part_api_urls)),
|
||||
|
||||
# Supplier price breaks
|
||||
url(r'^price-break/', include([
|
||||
re_path(r'^price-break/', include([
|
||||
|
||||
url(r'^(?P<pk>\d+)/?', SupplierPriceBreakDetail.as_view(), name='api-part-supplier-price-detail'),
|
||||
url(r'^.*$', SupplierPriceBreakList.as_view(), name='api-part-supplier-price-list'),
|
||||
re_path(r'^(?P<pk>\d+)/?', SupplierPriceBreakDetail.as_view(), name='api-part-supplier-price-detail'),
|
||||
re_path(r'^.*$', SupplierPriceBreakList.as_view(), name='api-part-supplier-price-list'),
|
||||
])),
|
||||
|
||||
url(r'^(?P<pk>\d+)/?', CompanyDetail.as_view(), name='api-company-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/?', CompanyDetail.as_view(), name='api-company-detail'),
|
||||
|
||||
url(r'^.*$', CompanyList.as_view(), name='api-company-list'),
|
||||
re_path(r'^.*$', CompanyList.as_view(), name='api-company-list'),
|
||||
]
|
||||
|
@ -8,7 +8,7 @@ from __future__ import unicode_literals
|
||||
from InvenTree.forms import HelperForm
|
||||
from InvenTree.fields import RoundingDecimalFormField
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import django.forms
|
||||
|
||||
from .models import Company
|
||||
|
@ -7,7 +7,7 @@ from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.core.validators import MinValueValidator
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
JSON serializers for Company app
|
||||
"""
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
|
@ -2,37 +2,37 @@
|
||||
URL lookup for Company app
|
||||
"""
|
||||
|
||||
from django.conf.urls import url, include
|
||||
from django.urls import include, re_path
|
||||
|
||||
from . import views
|
||||
|
||||
|
||||
company_detail_urls = [
|
||||
|
||||
url(r'^thumb-download/', views.CompanyImageDownloadFromURL.as_view(), name='company-image-download'),
|
||||
re_path(r'^thumb-download/', views.CompanyImageDownloadFromURL.as_view(), name='company-image-download'),
|
||||
|
||||
# Any other URL
|
||||
url(r'^.*$', views.CompanyDetail.as_view(), name='company-detail'),
|
||||
re_path(r'^.*$', views.CompanyDetail.as_view(), name='company-detail'),
|
||||
]
|
||||
|
||||
|
||||
company_urls = [
|
||||
|
||||
url(r'^(?P<pk>\d+)/', include(company_detail_urls)),
|
||||
re_path(r'^(?P<pk>\d+)/', include(company_detail_urls)),
|
||||
|
||||
url(r'suppliers/', views.CompanyIndex.as_view(), name='supplier-index'),
|
||||
url(r'manufacturers/', views.CompanyIndex.as_view(), name='manufacturer-index'),
|
||||
url(r'customers/', views.CompanyIndex.as_view(), name='customer-index'),
|
||||
re_path(r'suppliers/', views.CompanyIndex.as_view(), name='supplier-index'),
|
||||
re_path(r'manufacturers/', views.CompanyIndex.as_view(), name='manufacturer-index'),
|
||||
re_path(r'customers/', views.CompanyIndex.as_view(), name='customer-index'),
|
||||
|
||||
# Redirect any other patterns to the 'company' index which displays all companies
|
||||
url(r'^.*$', views.CompanyIndex.as_view(), name='company-index'),
|
||||
re_path(r'^.*$', views.CompanyIndex.as_view(), name='company-index'),
|
||||
]
|
||||
|
||||
manufacturer_part_urls = [
|
||||
|
||||
url(r'^(?P<pk>\d+)/', views.ManufacturerPartDetail.as_view(template_name='company/manufacturer_part.html'), name='manufacturer-part-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/', views.ManufacturerPartDetail.as_view(template_name='company/manufacturer_part.html'), name='manufacturer-part-detail'),
|
||||
]
|
||||
|
||||
supplier_part_urls = [
|
||||
url(r'^(?P<pk>\d+)/', views.SupplierPartDetail.as_view(template_name='company/supplier_part.html'), name='supplier-part-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/', views.SupplierPartDetail.as_view(template_name='company/supplier_part.html'), name='supplier-part-detail'),
|
||||
]
|
||||
|
@ -6,7 +6,7 @@ Django views for interacting with Company app
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import DetailView, ListView
|
||||
|
||||
from django.urls import reverse
|
||||
|
@ -4,10 +4,10 @@ from __future__ import unicode_literals
|
||||
from io import BytesIO
|
||||
from PIL import Image
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from django.conf import settings
|
||||
from django.conf.urls import url, include
|
||||
from django.urls import include, re_path
|
||||
from django.core.exceptions import ValidationError, FieldError
|
||||
from django.http import HttpResponse, JsonResponse
|
||||
|
||||
@ -579,38 +579,38 @@ class PartLabelPrint(generics.RetrieveAPIView, PartLabelMixin, LabelPrintMixin):
|
||||
label_api_urls = [
|
||||
|
||||
# Stock item labels
|
||||
url(r'stock/', include([
|
||||
re_path(r'stock/', include([
|
||||
# Detail views
|
||||
url(r'^(?P<pk>\d+)/', include([
|
||||
url(r'print/?', StockItemLabelPrint.as_view(), name='api-stockitem-label-print'),
|
||||
url(r'^.*$', StockItemLabelDetail.as_view(), name='api-stockitem-label-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
re_path(r'print/?', StockItemLabelPrint.as_view(), name='api-stockitem-label-print'),
|
||||
re_path(r'^.*$', StockItemLabelDetail.as_view(), name='api-stockitem-label-detail'),
|
||||
])),
|
||||
|
||||
# List view
|
||||
url(r'^.*$', StockItemLabelList.as_view(), name='api-stockitem-label-list'),
|
||||
re_path(r'^.*$', StockItemLabelList.as_view(), name='api-stockitem-label-list'),
|
||||
])),
|
||||
|
||||
# Stock location labels
|
||||
url(r'location/', include([
|
||||
re_path(r'location/', include([
|
||||
# Detail views
|
||||
url(r'^(?P<pk>\d+)/', include([
|
||||
url(r'print/?', StockLocationLabelPrint.as_view(), name='api-stocklocation-label-print'),
|
||||
url(r'^.*$', StockLocationLabelDetail.as_view(), name='api-stocklocation-label-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
re_path(r'print/?', StockLocationLabelPrint.as_view(), name='api-stocklocation-label-print'),
|
||||
re_path(r'^.*$', StockLocationLabelDetail.as_view(), name='api-stocklocation-label-detail'),
|
||||
])),
|
||||
|
||||
# List view
|
||||
url(r'^.*$', StockLocationLabelList.as_view(), name='api-stocklocation-label-list'),
|
||||
re_path(r'^.*$', StockLocationLabelList.as_view(), name='api-stocklocation-label-list'),
|
||||
])),
|
||||
|
||||
# Part labels
|
||||
url(r'^part/', include([
|
||||
re_path(r'^part/', include([
|
||||
# Detail views
|
||||
url(r'^(?P<pk>\d+)/', include([
|
||||
url(r'^print/', PartLabelPrint.as_view(), name='api-part-label-print'),
|
||||
url(r'^.*$', PartLabelDetail.as_view(), name='api-part-label-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
re_path(r'^print/', PartLabelPrint.as_view(), name='api-part-label-print'),
|
||||
re_path(r'^.*$', PartLabelDetail.as_view(), name='api-part-label-detail'),
|
||||
])),
|
||||
|
||||
# List view
|
||||
url(r'^.*$', PartLabelList.as_view(), name='api-part-label-list'),
|
||||
re_path(r'^.*$', PartLabelList.as_view(), name='api-part-label-list'),
|
||||
])),
|
||||
]
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,7 @@ JSON API for the Order app
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf.urls import url, include
|
||||
from django.urls import include, path, re_path
|
||||
from django.db.models import Q, F
|
||||
|
||||
from django_filters import rest_framework as rest_filters
|
||||
@ -1096,78 +1096,78 @@ class PurchaseOrderAttachmentDetail(generics.RetrieveUpdateDestroyAPIView, Attac
|
||||
order_api_urls = [
|
||||
|
||||
# API endpoints for purchase orders
|
||||
url(r'^po/', include([
|
||||
re_path(r'^po/', include([
|
||||
|
||||
# Purchase order attachments
|
||||
url(r'attachment/', include([
|
||||
url(r'^(?P<pk>\d+)/$', PurchaseOrderAttachmentDetail.as_view(), name='api-po-attachment-detail'),
|
||||
url(r'^.*$', PurchaseOrderAttachmentList.as_view(), name='api-po-attachment-list'),
|
||||
re_path(r'attachment/', include([
|
||||
path('<int:pk>/', PurchaseOrderAttachmentDetail.as_view(), name='api-po-attachment-detail'),
|
||||
re_path(r'^.*$', PurchaseOrderAttachmentList.as_view(), name='api-po-attachment-list'),
|
||||
])),
|
||||
|
||||
# Individual purchase order detail URLs
|
||||
url(r'^(?P<pk>\d+)/', include([
|
||||
url(r'^receive/', PurchaseOrderReceive.as_view(), name='api-po-receive'),
|
||||
url(r'.*$', PurchaseOrderDetail.as_view(), name='api-po-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
re_path(r'^receive/', PurchaseOrderReceive.as_view(), name='api-po-receive'),
|
||||
re_path(r'.*$', PurchaseOrderDetail.as_view(), name='api-po-detail'),
|
||||
])),
|
||||
|
||||
# Purchase order list
|
||||
url(r'^.*$', PurchaseOrderList.as_view(), name='api-po-list'),
|
||||
re_path(r'^.*$', PurchaseOrderList.as_view(), name='api-po-list'),
|
||||
])),
|
||||
|
||||
# API endpoints for purchase order line items
|
||||
url(r'^po-line/', include([
|
||||
url(r'^(?P<pk>\d+)/$', PurchaseOrderLineItemDetail.as_view(), name='api-po-line-detail'),
|
||||
url(r'^.*$', PurchaseOrderLineItemList.as_view(), name='api-po-line-list'),
|
||||
re_path(r'^po-line/', include([
|
||||
path('<int:pk>/', PurchaseOrderLineItemDetail.as_view(), name='api-po-line-detail'),
|
||||
re_path(r'^.*$', PurchaseOrderLineItemList.as_view(), name='api-po-line-list'),
|
||||
])),
|
||||
|
||||
# API endpoints for purchase order extra line
|
||||
url(r'^po-extra-line/', include([
|
||||
url(r'^(?P<pk>\d+)/$', PurchaseOrderExtraLineDetail.as_view(), name='api-po-extra-line-detail'),
|
||||
url(r'^$', PurchaseOrderExtraLineList.as_view(), name='api-po-extra-line-list'),
|
||||
re_path(r'^po-extra-line/', include([
|
||||
path('<int:pk>/', PurchaseOrderExtraLineDetail.as_view(), name='api-po-extra-line-detail'),
|
||||
path('', PurchaseOrderExtraLineList.as_view(), name='api-po-extra-line-list'),
|
||||
])),
|
||||
|
||||
# API endpoints for sales ordesr
|
||||
url(r'^so/', include([
|
||||
url(r'attachment/', include([
|
||||
url(r'^(?P<pk>\d+)/$', SalesOrderAttachmentDetail.as_view(), name='api-so-attachment-detail'),
|
||||
url(r'^.*$', SalesOrderAttachmentList.as_view(), name='api-so-attachment-list'),
|
||||
re_path(r'^so/', include([
|
||||
re_path(r'attachment/', include([
|
||||
path('<int:pk>/', SalesOrderAttachmentDetail.as_view(), name='api-so-attachment-detail'),
|
||||
re_path(r'^.*$', SalesOrderAttachmentList.as_view(), name='api-so-attachment-list'),
|
||||
])),
|
||||
|
||||
url(r'^shipment/', include([
|
||||
url(r'^(?P<pk>\d+)/', include([
|
||||
url(r'^ship/$', SalesOrderShipmentComplete.as_view(), name='api-so-shipment-ship'),
|
||||
url(r'^.*$', SalesOrderShipmentDetail.as_view(), name='api-so-shipment-detail'),
|
||||
re_path(r'^shipment/', include([
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
path('ship/', SalesOrderShipmentComplete.as_view(), name='api-so-shipment-ship'),
|
||||
re_path(r'^.*$', SalesOrderShipmentDetail.as_view(), name='api-so-shipment-detail'),
|
||||
])),
|
||||
url(r'^.*$', SalesOrderShipmentList.as_view(), name='api-so-shipment-list'),
|
||||
re_path(r'^.*$', SalesOrderShipmentList.as_view(), name='api-so-shipment-list'),
|
||||
])),
|
||||
|
||||
# Sales order detail view
|
||||
url(r'^(?P<pk>\d+)/', include([
|
||||
url(r'^complete/', SalesOrderComplete.as_view(), name='api-so-complete'),
|
||||
url(r'^allocate/', SalesOrderAllocate.as_view(), name='api-so-allocate'),
|
||||
url(r'^allocate-serials/', SalesOrderAllocateSerials.as_view(), name='api-so-allocate-serials'),
|
||||
url(r'^.*$', SalesOrderDetail.as_view(), name='api-so-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
re_path(r'^complete/', SalesOrderComplete.as_view(), name='api-so-complete'),
|
||||
re_path(r'^allocate/', SalesOrderAllocate.as_view(), name='api-so-allocate'),
|
||||
re_path(r'^allocate-serials/', SalesOrderAllocateSerials.as_view(), name='api-so-allocate-serials'),
|
||||
re_path(r'^.*$', SalesOrderDetail.as_view(), name='api-so-detail'),
|
||||
])),
|
||||
|
||||
# Sales order list view
|
||||
url(r'^.*$', SalesOrderList.as_view(), name='api-so-list'),
|
||||
re_path(r'^.*$', SalesOrderList.as_view(), name='api-so-list'),
|
||||
])),
|
||||
|
||||
# API endpoints for sales order line items
|
||||
url(r'^so-line/', include([
|
||||
url(r'^(?P<pk>\d+)/$', SalesOrderLineItemDetail.as_view(), name='api-so-line-detail'),
|
||||
url(r'^$', SalesOrderLineItemList.as_view(), name='api-so-line-list'),
|
||||
re_path(r'^so-line/', include([
|
||||
path('<int:pk>/', SalesOrderLineItemDetail.as_view(), name='api-so-line-detail'),
|
||||
path('', SalesOrderLineItemList.as_view(), name='api-so-line-list'),
|
||||
])),
|
||||
|
||||
# API endpoints for sales order extra line
|
||||
url(r'^so-extra-line/', include([
|
||||
url(r'^(?P<pk>\d+)/$', SalesOrderExtraLineDetail.as_view(), name='api-so-extra-line-detail'),
|
||||
url(r'^$', SalesOrderExtraLineList.as_view(), name='api-so-extra-line-list'),
|
||||
re_path(r'^so-extra-line/', include([
|
||||
path('<int:pk>/', SalesOrderExtraLineDetail.as_view(), name='api-so-extra-line-detail'),
|
||||
path('', SalesOrderExtraLineList.as_view(), name='api-so-extra-line-list'),
|
||||
])),
|
||||
|
||||
# API endpoints for sales order allocations
|
||||
url(r'^so-allocation/', include([
|
||||
url(r'^(?P<pk>\d+)/$', SalesOrderAllocationDetail.as_view(), name='api-so-allocation-detail'),
|
||||
url(r'^.*$', SalesOrderAllocationList.as_view(), name='api-so-allocation-list'),
|
||||
re_path(r'^so-allocation/', include([
|
||||
path('<int:pk>/', SalesOrderAllocationDetail.as_view(), name='api-so-allocation-detail'),
|
||||
re_path(r'^.*$', SalesOrderAllocationList.as_view(), name='api-so-allocation-list'),
|
||||
])),
|
||||
]
|
||||
|
@ -6,7 +6,7 @@ Django Forms for interacting with Order objects
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from InvenTree.forms import HelperForm
|
||||
from InvenTree.fields import InvenTreeMoneyField
|
||||
|
@ -33,7 +33,7 @@ def calculate_shipped_quantity(apps, schema_editor):
|
||||
part=item.part
|
||||
)
|
||||
|
||||
q = sum([item.quantity for item in items])
|
||||
q = sum(item.quantity for item in items)
|
||||
|
||||
item.shipped = q
|
||||
|
||||
|
@ -17,7 +17,7 @@ from django.core.validators import MinValueValidator
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.contrib.auth.models import User
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from markdownx.models import MarkdownxField
|
||||
from mptt.models import TreeForeignKey
|
||||
@ -49,7 +49,7 @@ def get_next_po_number():
|
||||
|
||||
order = PurchaseOrder.objects.exclude(reference=None).last()
|
||||
|
||||
attempts = set([order.reference])
|
||||
attempts = {order.reference}
|
||||
|
||||
reference = order.reference
|
||||
|
||||
@ -78,7 +78,7 @@ def get_next_so_number():
|
||||
|
||||
order = SalesOrder.objects.exclude(reference=None).last()
|
||||
|
||||
attempts = set([order.reference])
|
||||
attempts = {order.reference}
|
||||
|
||||
reference = order.reference
|
||||
|
||||
@ -161,10 +161,10 @@ class Order(ReferenceIndexingMixin):
|
||||
# gather name reference
|
||||
price_ref = 'sale_price' if isinstance(self, SalesOrder) else 'purchase_price'
|
||||
# order items
|
||||
total += sum([a.quantity * convert_money(getattr(a, price_ref), target_currency) for a in self.lines.all() if getattr(a, price_ref)])
|
||||
total += sum(a.quantity * convert_money(getattr(a, price_ref), target_currency) for a in self.lines.all() if getattr(a, price_ref))
|
||||
|
||||
# extra lines
|
||||
total += sum([a.quantity * convert_money(a.price, target_currency) for a in self.extra_lines.all() if a.price])
|
||||
total += sum(a.quantity * convert_money(a.price, target_currency) for a in self.extra_lines.all() if a.price)
|
||||
|
||||
# set decimal-places
|
||||
total.decimal_places = 4
|
||||
|
@ -7,7 +7,7 @@ from __future__ import unicode_literals
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from django.core.exceptions import ValidationError as DjangoValidationError
|
||||
from django.db import models, transaction
|
||||
|
@ -5,50 +5,50 @@ URL lookup for the Order app. Provides URL endpoints for:
|
||||
- Detail view of Purchase Orders
|
||||
"""
|
||||
|
||||
from django.conf.urls import url, include
|
||||
from django.urls import include, re_path
|
||||
|
||||
from . import views
|
||||
|
||||
purchase_order_detail_urls = [
|
||||
|
||||
url(r'^cancel/', views.PurchaseOrderCancel.as_view(), name='po-cancel'),
|
||||
url(r'^issue/', views.PurchaseOrderIssue.as_view(), name='po-issue'),
|
||||
url(r'^complete/', views.PurchaseOrderComplete.as_view(), name='po-complete'),
|
||||
re_path(r'^cancel/', views.PurchaseOrderCancel.as_view(), name='po-cancel'),
|
||||
re_path(r'^issue/', views.PurchaseOrderIssue.as_view(), name='po-issue'),
|
||||
re_path(r'^complete/', views.PurchaseOrderComplete.as_view(), name='po-complete'),
|
||||
|
||||
url(r'^upload/', views.PurchaseOrderUpload.as_view(), name='po-upload'),
|
||||
url(r'^export/', views.PurchaseOrderExport.as_view(), name='po-export'),
|
||||
re_path(r'^upload/', views.PurchaseOrderUpload.as_view(), name='po-upload'),
|
||||
re_path(r'^export/', views.PurchaseOrderExport.as_view(), name='po-export'),
|
||||
|
||||
url(r'^.*$', views.PurchaseOrderDetail.as_view(), name='po-detail'),
|
||||
re_path(r'^.*$', views.PurchaseOrderDetail.as_view(), name='po-detail'),
|
||||
]
|
||||
|
||||
purchase_order_urls = [
|
||||
|
||||
url(r'^order-parts/', views.OrderParts.as_view(), name='order-parts'),
|
||||
url(r'^pricing/', views.LineItemPricing.as_view(), name='line-pricing'),
|
||||
re_path(r'^order-parts/', views.OrderParts.as_view(), name='order-parts'),
|
||||
re_path(r'^pricing/', views.LineItemPricing.as_view(), name='line-pricing'),
|
||||
|
||||
# Display detail view for a single purchase order
|
||||
url(r'^(?P<pk>\d+)/', include(purchase_order_detail_urls)),
|
||||
re_path(r'^(?P<pk>\d+)/', include(purchase_order_detail_urls)),
|
||||
|
||||
# Display complete list of purchase orders
|
||||
url(r'^.*$', views.PurchaseOrderIndex.as_view(), name='po-index'),
|
||||
re_path(r'^.*$', views.PurchaseOrderIndex.as_view(), name='po-index'),
|
||||
]
|
||||
|
||||
sales_order_detail_urls = [
|
||||
url(r'^cancel/', views.SalesOrderCancel.as_view(), name='so-cancel'),
|
||||
url(r'^export/', views.SalesOrderExport.as_view(), name='so-export'),
|
||||
re_path(r'^cancel/', views.SalesOrderCancel.as_view(), name='so-cancel'),
|
||||
re_path(r'^export/', views.SalesOrderExport.as_view(), name='so-export'),
|
||||
|
||||
url(r'^.*$', views.SalesOrderDetail.as_view(), name='so-detail'),
|
||||
re_path(r'^.*$', views.SalesOrderDetail.as_view(), name='so-detail'),
|
||||
]
|
||||
|
||||
sales_order_urls = [
|
||||
# Display detail view for a single SalesOrder
|
||||
url(r'^(?P<pk>\d+)/', include(sales_order_detail_urls)),
|
||||
re_path(r'^(?P<pk>\d+)/', include(sales_order_detail_urls)),
|
||||
|
||||
# Display list of all sales orders
|
||||
url(r'^.*$', views.SalesOrderIndex.as_view(), name='so-index'),
|
||||
re_path(r'^.*$', views.SalesOrderIndex.as_view(), name='so-index'),
|
||||
]
|
||||
|
||||
order_urls = [
|
||||
url(r'^purchase-order/', include(purchase_order_urls)),
|
||||
url(r'^sales-order/', include(sales_order_urls)),
|
||||
re_path(r'^purchase-order/', include(purchase_order_urls)),
|
||||
re_path(r'^sales-order/', include(sales_order_urls)),
|
||||
]
|
||||
|
@ -11,7 +11,7 @@ from django.http.response import JsonResponse
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import DetailView, ListView
|
||||
from django.forms import HiddenInput, IntegerField
|
||||
|
||||
|
@ -7,11 +7,11 @@ from __future__ import unicode_literals
|
||||
|
||||
import datetime
|
||||
|
||||
from django.conf.urls import url, include
|
||||
from django.urls import include, path, re_path
|
||||
from django.http import JsonResponse
|
||||
from django.db.models import Q, F, Count, Min, Max, Avg
|
||||
from django.db import transaction
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework import status
|
||||
from rest_framework.response import Response
|
||||
@ -1916,100 +1916,100 @@ class BomItemSubstituteDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||
part_api_urls = [
|
||||
|
||||
# Base URL for PartCategory API endpoints
|
||||
url(r'^category/', include([
|
||||
url(r'^tree/', CategoryTree.as_view(), name='api-part-category-tree'),
|
||||
url(r'^parameters/', CategoryParameterList.as_view(), name='api-part-category-parameter-list'),
|
||||
re_path(r'^category/', include([
|
||||
re_path(r'^tree/', CategoryTree.as_view(), name='api-part-category-tree'),
|
||||
re_path(r'^parameters/', CategoryParameterList.as_view(), name='api-part-category-parameter-list'),
|
||||
|
||||
url(r'^(?P<pk>\d+)/?', CategoryDetail.as_view(), name='api-part-category-detail'),
|
||||
url(r'^$', CategoryList.as_view(), name='api-part-category-list'),
|
||||
re_path(r'^(?P<pk>\d+)/?', CategoryDetail.as_view(), name='api-part-category-detail'),
|
||||
path('', CategoryList.as_view(), name='api-part-category-list'),
|
||||
])),
|
||||
|
||||
# Base URL for PartTestTemplate API endpoints
|
||||
url(r'^test-template/', include([
|
||||
url(r'^(?P<pk>\d+)/', PartTestTemplateDetail.as_view(), name='api-part-test-template-detail'),
|
||||
url(r'^$', PartTestTemplateList.as_view(), name='api-part-test-template-list'),
|
||||
re_path(r'^test-template/', include([
|
||||
re_path(r'^(?P<pk>\d+)/', PartTestTemplateDetail.as_view(), name='api-part-test-template-detail'),
|
||||
path('', PartTestTemplateList.as_view(), name='api-part-test-template-list'),
|
||||
])),
|
||||
|
||||
# Base URL for PartAttachment API endpoints
|
||||
url(r'^attachment/', include([
|
||||
url(r'^(?P<pk>\d+)/', PartAttachmentDetail.as_view(), name='api-part-attachment-detail'),
|
||||
url(r'^$', PartAttachmentList.as_view(), name='api-part-attachment-list'),
|
||||
re_path(r'^attachment/', include([
|
||||
re_path(r'^(?P<pk>\d+)/', PartAttachmentDetail.as_view(), name='api-part-attachment-detail'),
|
||||
path('', PartAttachmentList.as_view(), name='api-part-attachment-list'),
|
||||
])),
|
||||
|
||||
# Base URL for part sale pricing
|
||||
url(r'^sale-price/', include([
|
||||
url(r'^(?P<pk>\d+)/', PartSalePriceDetail.as_view(), name='api-part-sale-price-detail'),
|
||||
url(r'^.*$', PartSalePriceList.as_view(), name='api-part-sale-price-list'),
|
||||
re_path(r'^sale-price/', include([
|
||||
re_path(r'^(?P<pk>\d+)/', PartSalePriceDetail.as_view(), name='api-part-sale-price-detail'),
|
||||
re_path(r'^.*$', PartSalePriceList.as_view(), name='api-part-sale-price-list'),
|
||||
])),
|
||||
|
||||
# Base URL for part internal pricing
|
||||
url(r'^internal-price/', include([
|
||||
url(r'^(?P<pk>\d+)/', PartInternalPriceDetail.as_view(), name='api-part-internal-price-detail'),
|
||||
url(r'^.*$', PartInternalPriceList.as_view(), name='api-part-internal-price-list'),
|
||||
re_path(r'^internal-price/', include([
|
||||
re_path(r'^(?P<pk>\d+)/', PartInternalPriceDetail.as_view(), name='api-part-internal-price-detail'),
|
||||
re_path(r'^.*$', PartInternalPriceList.as_view(), name='api-part-internal-price-list'),
|
||||
])),
|
||||
|
||||
# Base URL for PartRelated API endpoints
|
||||
url(r'^related/', include([
|
||||
url(r'^(?P<pk>\d+)/', PartRelatedDetail.as_view(), name='api-part-related-detail'),
|
||||
url(r'^.*$', PartRelatedList.as_view(), name='api-part-related-list'),
|
||||
re_path(r'^related/', include([
|
||||
re_path(r'^(?P<pk>\d+)/', PartRelatedDetail.as_view(), name='api-part-related-detail'),
|
||||
re_path(r'^.*$', PartRelatedList.as_view(), name='api-part-related-list'),
|
||||
])),
|
||||
|
||||
# Base URL for PartParameter API endpoints
|
||||
url(r'^parameter/', include([
|
||||
url(r'^template/$', PartParameterTemplateList.as_view(), name='api-part-parameter-template-list'),
|
||||
re_path(r'^parameter/', include([
|
||||
path('template/', PartParameterTemplateList.as_view(), name='api-part-parameter-template-list'),
|
||||
|
||||
url(r'^(?P<pk>\d+)/', PartParameterDetail.as_view(), name='api-part-parameter-detail'),
|
||||
url(r'^.*$', PartParameterList.as_view(), name='api-part-parameter-list'),
|
||||
re_path(r'^(?P<pk>\d+)/', PartParameterDetail.as_view(), name='api-part-parameter-detail'),
|
||||
re_path(r'^.*$', PartParameterList.as_view(), name='api-part-parameter-list'),
|
||||
])),
|
||||
|
||||
url(r'^thumbs/', include([
|
||||
url(r'^$', PartThumbs.as_view(), name='api-part-thumbs'),
|
||||
url(r'^(?P<pk>\d+)/?', PartThumbsUpdate.as_view(), name='api-part-thumbs-update'),
|
||||
re_path(r'^thumbs/', include([
|
||||
path('', PartThumbs.as_view(), name='api-part-thumbs'),
|
||||
re_path(r'^(?P<pk>\d+)/?', PartThumbsUpdate.as_view(), name='api-part-thumbs-update'),
|
||||
])),
|
||||
|
||||
url(r'^(?P<pk>\d+)/', include([
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
|
||||
# Endpoint for extra serial number information
|
||||
url(r'^serial-numbers/', PartSerialNumberDetail.as_view(), name='api-part-serial-number-detail'),
|
||||
re_path(r'^serial-numbers/', PartSerialNumberDetail.as_view(), name='api-part-serial-number-detail'),
|
||||
|
||||
# Endpoint for future scheduling information
|
||||
url(r'^scheduling/', PartScheduling.as_view(), name='api-part-scheduling'),
|
||||
re_path(r'^scheduling/', PartScheduling.as_view(), name='api-part-scheduling'),
|
||||
|
||||
# Endpoint for duplicating a BOM for the specific Part
|
||||
url(r'^bom-copy/', PartCopyBOM.as_view(), name='api-part-bom-copy'),
|
||||
re_path(r'^bom-copy/', PartCopyBOM.as_view(), name='api-part-bom-copy'),
|
||||
|
||||
# Endpoint for validating a BOM for the specific Part
|
||||
url(r'^bom-validate/', PartValidateBOM.as_view(), name='api-part-bom-validate'),
|
||||
re_path(r'^bom-validate/', PartValidateBOM.as_view(), name='api-part-bom-validate'),
|
||||
|
||||
# Part detail endpoint
|
||||
url(r'^.*$', PartDetail.as_view(), name='api-part-detail'),
|
||||
re_path(r'^.*$', PartDetail.as_view(), name='api-part-detail'),
|
||||
])),
|
||||
|
||||
url(r'^.*$', PartList.as_view(), name='api-part-list'),
|
||||
re_path(r'^.*$', PartList.as_view(), name='api-part-list'),
|
||||
]
|
||||
|
||||
bom_api_urls = [
|
||||
|
||||
url(r'^substitute/', include([
|
||||
re_path(r'^substitute/', include([
|
||||
|
||||
# Detail view
|
||||
url(r'^(?P<pk>\d+)/', BomItemSubstituteDetail.as_view(), name='api-bom-substitute-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/', BomItemSubstituteDetail.as_view(), name='api-bom-substitute-detail'),
|
||||
|
||||
# Catch all
|
||||
url(r'^.*$', BomItemSubstituteList.as_view(), name='api-bom-substitute-list'),
|
||||
re_path(r'^.*$', BomItemSubstituteList.as_view(), name='api-bom-substitute-list'),
|
||||
])),
|
||||
|
||||
# BOM Item Detail
|
||||
url(r'^(?P<pk>\d+)/', include([
|
||||
url(r'^validate/?', BomItemValidate.as_view(), name='api-bom-item-validate'),
|
||||
url(r'^.*$', BomDetail.as_view(), name='api-bom-item-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
re_path(r'^validate/?', BomItemValidate.as_view(), name='api-bom-item-validate'),
|
||||
re_path(r'^.*$', BomDetail.as_view(), name='api-bom-item-detail'),
|
||||
])),
|
||||
|
||||
# API endpoint URLs for importing BOM data
|
||||
url(r'^import/upload/', BomImportUpload.as_view(), name='api-bom-import-upload'),
|
||||
url(r'^import/extract/', BomImportExtract.as_view(), name='api-bom-import-extract'),
|
||||
url(r'^import/submit/', BomImportSubmit.as_view(), name='api-bom-import-submit'),
|
||||
re_path(r'^import/upload/', BomImportUpload.as_view(), name='api-bom-import-upload'),
|
||||
re_path(r'^import/extract/', BomImportExtract.as_view(), name='api-bom-import-extract'),
|
||||
re_path(r'^import/submit/', BomImportSubmit.as_view(), name='api-bom-import-submit'),
|
||||
|
||||
# Catch-all
|
||||
url(r'^.*$', BomList.as_view(), name='api-bom-list'),
|
||||
re_path(r'^.*$', BomList.as_view(), name='api-bom-list'),
|
||||
]
|
||||
|
@ -6,7 +6,7 @@ Django Forms for interacting with Part objects
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from mptt.fields import TreeNodeChoiceField
|
||||
|
||||
|
@ -2510,7 +2510,7 @@ def validate_template_name(name):
|
||||
Prevent illegal characters in "name" field for PartParameterTemplate
|
||||
"""
|
||||
|
||||
for c in "!@#$%^&*()<>{}[].,?/\|~`_+-=\'\"":
|
||||
for c in "!@#$%^&*()<>{}[].,?/\\|~`_+-=\'\"":
|
||||
if c in str(name):
|
||||
raise ValidationError(_(f"Illegal character in template name ({c})"))
|
||||
|
||||
|
@ -11,7 +11,7 @@ from django.db.models import ExpressionWrapper, F, Q, Func
|
||||
from django.db.models import Subquery, OuterRef, FloatField
|
||||
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework import serializers
|
||||
from sql_util.utils import SubqueryCount, SubquerySum
|
||||
|
@ -3,7 +3,7 @@ from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
import InvenTree.helpers
|
||||
import InvenTree.tasks
|
||||
|
@ -12,7 +12,7 @@ import logging
|
||||
|
||||
from django.utils.html import format_html
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.conf import settings as djangosettings
|
||||
|
||||
from django import template
|
||||
|
@ -8,53 +8,53 @@ URL lookup for Part app. Provides URL endpoints for:
|
||||
|
||||
"""
|
||||
|
||||
from django.conf.urls import url, include
|
||||
from django.urls import include, re_path
|
||||
|
||||
from . import views
|
||||
|
||||
|
||||
part_parameter_urls = [
|
||||
url(r'^template/new/', views.PartParameterTemplateCreate.as_view(), name='part-param-template-create'),
|
||||
url(r'^template/(?P<pk>\d+)/edit/', views.PartParameterTemplateEdit.as_view(), name='part-param-template-edit'),
|
||||
url(r'^template/(?P<pk>\d+)/delete/', views.PartParameterTemplateDelete.as_view(), name='part-param-template-edit'),
|
||||
re_path(r'^template/new/', views.PartParameterTemplateCreate.as_view(), name='part-param-template-create'),
|
||||
re_path(r'^template/(?P<pk>\d+)/edit/', views.PartParameterTemplateEdit.as_view(), name='part-param-template-edit'),
|
||||
re_path(r'^template/(?P<pk>\d+)/delete/', views.PartParameterTemplateDelete.as_view(), name='part-param-template-edit'),
|
||||
]
|
||||
|
||||
part_detail_urls = [
|
||||
url(r'^delete/?', views.PartDelete.as_view(), name='part-delete'),
|
||||
url(r'^bom-download/?', views.BomDownload.as_view(), name='bom-download'),
|
||||
re_path(r'^delete/?', views.PartDelete.as_view(), name='part-delete'),
|
||||
re_path(r'^bom-download/?', views.BomDownload.as_view(), name='bom-download'),
|
||||
|
||||
url(r'^pricing/', views.PartPricing.as_view(), name='part-pricing'),
|
||||
re_path(r'^pricing/', views.PartPricing.as_view(), name='part-pricing'),
|
||||
|
||||
url(r'^bom-upload/?', views.BomUpload.as_view(), name='upload-bom'),
|
||||
re_path(r'^bom-upload/?', views.BomUpload.as_view(), name='upload-bom'),
|
||||
|
||||
url(r'^qr_code/?', views.PartQRCode.as_view(), name='part-qr'),
|
||||
re_path(r'^qr_code/?', views.PartQRCode.as_view(), name='part-qr'),
|
||||
|
||||
# Normal thumbnail with form
|
||||
url(r'^thumb-select/?', views.PartImageSelect.as_view(), name='part-image-select'),
|
||||
url(r'^thumb-download/', views.PartImageDownloadFromURL.as_view(), name='part-image-download'),
|
||||
re_path(r'^thumb-select/?', views.PartImageSelect.as_view(), name='part-image-select'),
|
||||
re_path(r'^thumb-download/', views.PartImageDownloadFromURL.as_view(), name='part-image-download'),
|
||||
|
||||
# Any other URLs go to the part detail page
|
||||
url(r'^.*$', views.PartDetail.as_view(), name='part-detail'),
|
||||
re_path(r'^.*$', views.PartDetail.as_view(), name='part-detail'),
|
||||
]
|
||||
|
||||
category_parameter_urls = [
|
||||
url(r'^new/', views.CategoryParameterTemplateCreate.as_view(), name='category-param-template-create'),
|
||||
url(r'^(?P<pid>\d+)/edit/', views.CategoryParameterTemplateEdit.as_view(), name='category-param-template-edit'),
|
||||
url(r'^(?P<pid>\d+)/delete/', views.CategoryParameterTemplateDelete.as_view(), name='category-param-template-delete'),
|
||||
re_path(r'^new/', views.CategoryParameterTemplateCreate.as_view(), name='category-param-template-create'),
|
||||
re_path(r'^(?P<pid>\d+)/edit/', views.CategoryParameterTemplateEdit.as_view(), name='category-param-template-edit'),
|
||||
re_path(r'^(?P<pid>\d+)/delete/', views.CategoryParameterTemplateDelete.as_view(), name='category-param-template-delete'),
|
||||
]
|
||||
|
||||
category_urls = [
|
||||
|
||||
# Top level subcategory display
|
||||
url(r'^subcategory/', views.PartIndex.as_view(template_name='part/subcategory.html'), name='category-index-subcategory'),
|
||||
re_path(r'^subcategory/', views.PartIndex.as_view(template_name='part/subcategory.html'), name='category-index-subcategory'),
|
||||
|
||||
# Category detail views
|
||||
url(r'(?P<pk>\d+)/', include([
|
||||
url(r'^delete/', views.CategoryDelete.as_view(), name='category-delete'),
|
||||
url(r'^parameters/', include(category_parameter_urls)),
|
||||
re_path(r'(?P<pk>\d+)/', include([
|
||||
re_path(r'^delete/', views.CategoryDelete.as_view(), name='category-delete'),
|
||||
re_path(r'^parameters/', include(category_parameter_urls)),
|
||||
|
||||
# Anything else
|
||||
url(r'^.*$', views.CategoryDetail.as_view(), name='category-detail'),
|
||||
re_path(r'^.*$', views.CategoryDetail.as_view(), name='category-detail'),
|
||||
]))
|
||||
]
|
||||
|
||||
@ -62,27 +62,27 @@ category_urls = [
|
||||
part_urls = [
|
||||
|
||||
# Upload a part
|
||||
url(r'^import/', views.PartImport.as_view(), name='part-import'),
|
||||
url(r'^import-api/', views.PartImportAjax.as_view(), name='api-part-import'),
|
||||
re_path(r'^import/', views.PartImport.as_view(), name='part-import'),
|
||||
re_path(r'^import-api/', views.PartImportAjax.as_view(), name='api-part-import'),
|
||||
|
||||
# Download a BOM upload template
|
||||
url(r'^bom_template/?', views.BomUploadTemplate.as_view(), name='bom-upload-template'),
|
||||
re_path(r'^bom_template/?', views.BomUploadTemplate.as_view(), name='bom-upload-template'),
|
||||
|
||||
# Individual part using pk
|
||||
url(r'^(?P<pk>\d+)/', include(part_detail_urls)),
|
||||
re_path(r'^(?P<pk>\d+)/', include(part_detail_urls)),
|
||||
|
||||
# Part category
|
||||
url(r'^category/', include(category_urls)),
|
||||
re_path(r'^category/', include(category_urls)),
|
||||
|
||||
# Part parameters
|
||||
url(r'^parameter/', include(part_parameter_urls)),
|
||||
re_path(r'^parameter/', include(part_parameter_urls)),
|
||||
|
||||
# Change category for multiple parts
|
||||
url(r'^set-category/?', views.PartSetCategory.as_view(), name='part-set-category'),
|
||||
re_path(r'^set-category/?', views.PartSetCategory.as_view(), name='part-set-category'),
|
||||
|
||||
# Individual part using IPN as slug
|
||||
url(r'^(?P<slug>[-\w]+)/', views.PartDetailFromIPN.as_view(), name='part-detail-from-ipn'),
|
||||
re_path(r'^(?P<slug>[-\w]+)/', views.PartDetailFromIPN.as_view(), name='part-detail-from-ipn'),
|
||||
|
||||
# Top level part list (display top level parts and categories)
|
||||
url(r'^.*$', views.PartIndex.as_view(), name='part-index'),
|
||||
re_path(r'^.*$', views.PartIndex.as_view(), name='part-index'),
|
||||
]
|
||||
|
@ -5,7 +5,7 @@ JSON API for the plugin app
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf.urls import url, include
|
||||
from django.urls import include, re_path
|
||||
|
||||
from rest_framework import generics
|
||||
from rest_framework import status
|
||||
@ -118,18 +118,18 @@ class PluginSettingDetail(generics.RetrieveUpdateAPIView):
|
||||
plugin_api_urls = [
|
||||
|
||||
# Plugin settings URLs
|
||||
url(r'^settings/', include([
|
||||
url(r'^(?P<pk>\d+)/', PluginSettingDetail.as_view(), name='api-plugin-setting-detail'),
|
||||
url(r'^.*$', PluginSettingList.as_view(), name='api-plugin-setting-list'),
|
||||
re_path(r'^settings/', include([
|
||||
re_path(r'^(?P<pk>\d+)/', PluginSettingDetail.as_view(), name='api-plugin-setting-detail'),
|
||||
re_path(r'^.*$', PluginSettingList.as_view(), name='api-plugin-setting-list'),
|
||||
])),
|
||||
|
||||
# Detail views for a single PluginConfig item
|
||||
url(r'^(?P<pk>\d+)/', include([
|
||||
url(r'^.*$', PluginDetail.as_view(), name='api-plugin-detail'),
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
re_path(r'^.*$', PluginDetail.as_view(), name='api-plugin-detail'),
|
||||
])),
|
||||
|
||||
url(r'^install/', PluginInstall.as_view(), name='api-plugin-install'),
|
||||
re_path(r'^install/', PluginInstall.as_view(), name='api-plugin-install'),
|
||||
|
||||
# Anything else
|
||||
url(r'^.*$', PluginList.as_view(), name='api-plugin-list'),
|
||||
re_path(r'^.*$', PluginList.as_view(), name='api-plugin-list'),
|
||||
]
|
||||
|
@ -5,7 +5,7 @@ import logging
|
||||
|
||||
from django.apps import AppConfig
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from maintenance_mode.core import set_maintenance_mode
|
||||
|
||||
|
@ -6,7 +6,7 @@ import logging
|
||||
import json
|
||||
import requests
|
||||
|
||||
from django.conf.urls import url, include
|
||||
from django.urls import include, re_path
|
||||
from django.db.utils import OperationalError, ProgrammingError
|
||||
|
||||
from plugin.models import PluginConfig, PluginSetting
|
||||
@ -303,7 +303,7 @@ class UrlsMixin:
|
||||
Urlpatterns for this plugin
|
||||
"""
|
||||
if self.has_urls:
|
||||
return url(f'^{self.slug}/', include((self.urls, self.slug)), name=self.slug)
|
||||
return re_path(f'^{self.slug}/', include((self.urls, self.slug)), name=self.slug)
|
||||
return None
|
||||
|
||||
@property
|
||||
|
@ -7,7 +7,7 @@ from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import transaction
|
||||
|
@ -11,7 +11,7 @@ import pathlib
|
||||
|
||||
from django.urls.base import reverse
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
import plugin.plugin as plugin_base
|
||||
from plugin.helpers import get_git_log, GitStatus
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user