Compare commits
64 Commits
main
...
bx-581-sta
Author | SHA1 | Date |
---|---|---|
|
5b4db31b68 | |
|
2750cea9c4 | |
|
639857b310 | |
|
f89a1f365a | |
|
65b340b873 | |
|
44fb008fd6 | |
|
69fc2eabd8 | |
|
cece90eaa2 | |
|
e8448a91db | |
|
ba0e8ba0d3 | |
|
2a41108ced | |
|
a65fdc02d5 | |
|
c143650bdd | |
|
c4dac25528 | |
|
e6b95be013 | |
|
7bdf4c628d | |
|
28406ad98a | |
|
61d6823e5f | |
|
0c95cda20d | |
|
cf9998c5f9 | |
|
153b7f601e | |
|
a56dcbd4d2 | |
|
877f99f466 | |
|
2e361ff919 | |
|
642b8ca73d | |
|
43668907f0 | |
|
66a298e101 | |
|
15c54bd3e6 | |
|
2dbd6742f7 | |
|
01ba1b8bce | |
|
cb45928ebd | |
|
69672c8721 | |
|
a23e604954 | |
|
516e06b3df | |
|
ef56974447 | |
|
46c3995b6f | |
|
def5f8873f | |
|
e7a91b0014 | |
|
c2edb2fe2a | |
|
659e1ee439 | |
|
fa49de322d | |
|
dd32cf6432 | |
|
43fb670765 | |
|
1dab0e2cc7 | |
|
14c0054d7f | |
|
8c7e4332dd | |
|
e1e353bc51 | |
|
58934e8666 | |
|
b71ebfc398 | |
|
698f791920 | |
|
ebc48e3b87 | |
|
2fad0b67d2 | |
|
2e8cc9f387 | |
|
7b2d7ff294 | |
|
f2f8a62fa2 | |
|
cbfc7daf6f | |
|
2332532236 | |
|
100d78a53b | |
|
2e09d6dcd4 | |
|
7b89dd25e7 | |
|
a21ee1d965 | |
|
a939178e3f | |
|
2c5d3ffe10 | |
|
34db8582e7 |
|
@ -0,0 +1,6 @@
|
|||
DB_NAME=
|
||||
DB_USER=
|
||||
DB_PASSWORD=
|
||||
DB_HOST=
|
||||
DB_PORT=
|
||||
ODATA_AUTH=
|
|
@ -0,0 +1,4 @@
|
|||
.idea/
|
||||
.vscode/
|
||||
.venv/
|
||||
.env
|
|
@ -1,3 +0,0 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
|
@ -1,6 +0,0 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.12 (Course_FirstProject) (3)" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (Course_FirstProject) (3)" project-jdk-type="Python SDK" />
|
||||
<component name="PyCharmProfessionalAdvertiser">
|
||||
<option name="shown" value="true" />
|
||||
</component>
|
||||
</project>
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/to_inventory.iml" filepath="$PROJECT_DIR$/.idea/to_inventory.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="PyDocumentationSettings">
|
||||
<option name="format" value="PLAIN" />
|
||||
<option name="myDocStringFormat" value="Plain" />
|
||||
</component>
|
||||
</module>
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -87,3 +87,6 @@ local_settings.py
|
|||
|
||||
.env
|
||||
db.sqlite3
|
||||
|
||||
.pgpass
|
||||
/*/migrations/0*
|
|
@ -0,0 +1,17 @@
|
|||
FROM ci.svs-tech.pro/library/node:22-bookworm-slim
|
||||
|
||||
ENV WORKING_DIR=/app
|
||||
WORKDIR ${WORKING_DIR}
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get install python3-pip -y
|
||||
RUN apt-get install python3-poetry -y
|
||||
|
||||
RUN poetry -vvv --version
|
||||
|
||||
COPY pyproject.toml poetry.lock ./
|
||||
RUN poetry install
|
||||
|
||||
COPY . ${WORKING_DIR}
|
||||
|
||||
CMD ["poetry", "run", "python", "manage.py", "runserver", "0.0.0.0:8000"]
|
|
@ -1,18 +0,0 @@
|
|||
from django.db import models
|
||||
|
||||
class Counter_agent(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
|
||||
def __str__(self):
|
||||
return f' Counter_agent {self.id}'
|
||||
|
||||
class element(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
external_id = models.IntegerField()
|
||||
type = models.CharField(max_length=100)
|
||||
photo = models.ImageField(upload_to='.')
|
||||
dop_text = models.TextField()
|
||||
Counter_agent = models.ForeignKey(Counter_agent, related_name='element', on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self):
|
||||
return f' element {self.id} (Counter_agent {self.Counter_agent.id})'
|
|
@ -11,7 +11,10 @@ https://docs.djangoproject.com/en/5.0/ref/settings/
|
|||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import os
|
||||
import dotenv
|
||||
|
||||
dotenv.load_dotenv(os.path.join(os.path.dirname(os.path.dirname(__file__)), ".env"))
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
@ -20,64 +23,88 @@ BASE_DIR = Path(__file__).resolve().parent.parent
|
|||
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = 'django-insecure-ruo!wst&sb8(f9)j5u4rda-w!673lj_-c0a%gx_t@)ff*q*2ze'
|
||||
SECRET_KEY = "django-insecure-ruo!wst&sb8(f9)j5u4rda-w!673lj_-c0a%gx_t@)ff*q*2ze"
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
NGROK_TEMP = "5f4c-193-228-134-167.ngrok-free.app"
|
||||
ALLOWED_HOSTS = [
|
||||
"localhost",
|
||||
NGROK_TEMP,
|
||||
"192.168.103.159",
|
||||
"back",
|
||||
]
|
||||
CORS_ALLOWED_ORIGINS = [
|
||||
"http://localhost:3000",
|
||||
"http://192.168.103.159:3000",
|
||||
]
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'inventory.apps.PostsConfig'
|
||||
"corsheaders",
|
||||
"rest_framework",
|
||||
"inventory",
|
||||
"tgbot",
|
||||
"django.contrib.admin",
|
||||
"django.contrib.auth",
|
||||
"django.contrib.contenttypes",
|
||||
"django.contrib.sessions",
|
||||
"django.contrib.messages",
|
||||
"django.contrib.staticfiles",
|
||||
"tmc",
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"corsheaders.middleware.CorsMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'api.urls'
|
||||
ROOT_URLCONF = "api.urls"
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
"DIRS": [],
|
||||
"APP_DIRS": True,
|
||||
"OPTIONS": {
|
||||
"context_processors": [
|
||||
"django.template.context_processors.debug",
|
||||
"django.template.context_processors.request",
|
||||
"django.contrib.auth.context_processors.auth",
|
||||
"django.contrib.messages.context_processors.messages",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = 'api.wsgi.application'
|
||||
WSGI_APPLICATION = "api.wsgi.application"
|
||||
|
||||
# Rest Framework
|
||||
REST_FRAMEWORK = {
|
||||
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
|
||||
"PAGE_SIZE": 10,
|
||||
}
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': BASE_DIR / 'db.sqlite3',
|
||||
"default": {
|
||||
"ENGINE": "django.db.backends.postgresql",
|
||||
"NAME": os.environ.get("DB_NAME"),
|
||||
"USER": os.environ.get("DB_USER"),
|
||||
"PASSWORD": os.environ.get("DB_PASSWORD"),
|
||||
"HOST": os.environ.get("DB_HOST"),
|
||||
"PORT": os.environ.get("DB_PORT"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,16 +114,16 @@ DATABASES = {
|
|||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
|
||||
},
|
||||
]
|
||||
|
||||
|
@ -104,9 +131,9 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/5.0/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
LANGUAGE_CODE = "en-us"
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
TIME_ZONE = "UTC"
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
|
@ -116,9 +143,47 @@ USE_TZ = True
|
|||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/5.0/howto/static-files/
|
||||
|
||||
STATIC_URL = 'static/'
|
||||
STATIC_URL = "static/"
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
||||
|
||||
LOGGING = {
|
||||
"version": 1,
|
||||
"disable_existing_loggers": False,
|
||||
"formatters": {
|
||||
"verbose": {
|
||||
"format": "{levelname} {asctime} {module} {process:d} {thread:d} {message}",
|
||||
"style": "{",
|
||||
},
|
||||
"large": {
|
||||
"format": "%(asctime)s %(levelname)s %(process)d %(filename)s:%(lineno)d "
|
||||
+ "%(funcName)s %(message)s "
|
||||
},
|
||||
"simple": {
|
||||
"format": "{levelname} {asctime} {module} {message}",
|
||||
"style": "{",
|
||||
},
|
||||
},
|
||||
"handlers": {
|
||||
"console": {
|
||||
"level": "INFO",
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "large",
|
||||
},
|
||||
},
|
||||
"root": {
|
||||
"handlers": ["console"],
|
||||
"level": "INFO",
|
||||
},
|
||||
}
|
||||
|
||||
ODATA_AUTH = os.environ.get("ODATA_AUTH")
|
||||
|
||||
TGBOT = {
|
||||
"token": os.environ.get("TG_TOKEN"),
|
||||
"base_url": NGROK_TEMP,
|
||||
"webhook": "webhook",
|
||||
}
|
||||
|
|
|
@ -15,8 +15,20 @@ Including another URLconf
|
|||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path
|
||||
from django.urls import include, path
|
||||
from rest_framework import routers
|
||||
|
||||
from inventory import views
|
||||
from tgbot import views as tgbot_views
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
router.register(r'api/partner', views.PartnerViewSet)
|
||||
router.register(r'api/element', views.ElementViewSet)
|
||||
router.register(r'api/inventory', views.InventoryItemViewSet)
|
||||
router.register(r'api/tgbot', tgbot_views.ItemViewSet)
|
||||
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
|
||||
path('admin/', admin.site.urls),
|
||||
]
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
from django.contrib import admin
|
||||
from .models import Partner, Element
|
||||
|
||||
admin.site.register(Partner)
|
||||
admin.site.register(Element)
|
|
@ -0,0 +1,46 @@
|
|||
from django.db import models
|
||||
|
||||
|
||||
class Partner(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=255)
|
||||
external_id = models.CharField()
|
||||
|
||||
def __str__(self):
|
||||
return f"Partner {self.id}"
|
||||
|
||||
|
||||
class Author(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=255)
|
||||
telegram_id = models.CharField(max_length=50)
|
||||
|
||||
def str(self):
|
||||
return f"Author {self.id} - {self.name}"
|
||||
|
||||
|
||||
class InventoryItem(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
name = models.CharField(max_length=255)
|
||||
author = models.ForeignKey(Author, on_delete=models.CASCADE, null=True)
|
||||
partner = models.ForeignKey(
|
||||
Partner, related_name="Inventory", on_delete=models.CASCADE
|
||||
)
|
||||
|
||||
|
||||
class Element(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
external_id = models.CharField()
|
||||
element_id = models.CharField(max_length=100)
|
||||
photo = models.ImageField(upload_to=".", null=True)
|
||||
additional_text = models.TextField(null=True, blank=True, default="")
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
inventory = models.ForeignKey(
|
||||
InventoryItem, related_name="Element", on_delete=models.CASCADE
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return f"Element {self.id} (Inventory {self.inventory.id})"
|
|
@ -0,0 +1,56 @@
|
|||
from rest_framework import serializers
|
||||
from rest_framework.validators import UniqueValidator
|
||||
|
||||
from .models import Element, InventoryItem, Partner
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger("root")
|
||||
|
||||
|
||||
class PartnerSerializer(serializers.ModelSerializer):
|
||||
total_inventory = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Partner
|
||||
fields = ["id", "external_id", "name", "total_inventory"]
|
||||
|
||||
def get_total_inventory(self, instance):
|
||||
return InventoryItem.objects.filter(partner=instance).count()
|
||||
|
||||
|
||||
class InventorySerializer(serializers.ModelSerializer):
|
||||
partner_name = serializers.CharField(source="partner.name", read_only=True)
|
||||
total_elements = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = InventoryItem
|
||||
fields = [
|
||||
"id",
|
||||
"name",
|
||||
"created_at",
|
||||
"total_elements",
|
||||
"partner",
|
||||
"partner_name",
|
||||
]
|
||||
|
||||
def get_total_elements(self, instance):
|
||||
return Element.objects.filter(inventory=instance).count()
|
||||
|
||||
|
||||
class ElementSerializer(serializers.ModelSerializer):
|
||||
inventory_name = serializers.CharField(source="inventory.name", read_only=True)
|
||||
element_id = serializers.CharField(
|
||||
max_length=100,
|
||||
validators=[UniqueValidator(queryset=Element.objects.all())]
|
||||
)
|
||||
class Meta:
|
||||
model = Element
|
||||
fields = [
|
||||
"id",
|
||||
"external_id",
|
||||
"element_id",
|
||||
"photo",
|
||||
"additional_text",
|
||||
"inventory",
|
||||
"inventory_name",
|
||||
]
|
|
@ -0,0 +1,251 @@
|
|||
import requests
|
||||
import datetime
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework import status
|
||||
from rest_framework.response import Response
|
||||
|
||||
from .models import Element, InventoryItem, Partner
|
||||
from .serializers import ElementSerializer, InventorySerializer, PartnerSerializer
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger("root")
|
||||
|
||||
|
||||
class PartnerViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
API endpoint that allows partners to be viewed or edited.
|
||||
"""
|
||||
|
||||
queryset = Partner.objects.all()
|
||||
serializer_class = PartnerSerializer
|
||||
|
||||
@action(detail=False, methods=["get"], url_path=r"external")
|
||||
def get_remote_partners(self, request):
|
||||
params = {
|
||||
"$format": "json",
|
||||
"$select": ",".join(["НаименованиеПолное", "Description", "Ref_Key"]),
|
||||
"$filter": "Недействителен eq false",
|
||||
}
|
||||
remote_url = (
|
||||
"https://1c.svs-tech.pro/UNF/odata/standard.odata/Catalog_Контрагенты?"
|
||||
+ "&".join([f"{p}={params[p]}" for p in params])
|
||||
)
|
||||
data = requests.get(remote_url, headers={"Authorization": settings.ODATA_AUTH})
|
||||
try:
|
||||
parsed_data = data.json()
|
||||
return Response(parsed_data["value"])
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
@action(detail=False, methods=["get"], url_path=r"external/(?P<cat_id>[^/.]+)")
|
||||
def get_remote_partner_one(self, request, cat_id):
|
||||
params = {
|
||||
"$format": "json",
|
||||
"$select": ",".join(["НаименованиеПолное", "Description", "Ref_Key"]),
|
||||
}
|
||||
remote_url = (
|
||||
f"https://1c.svs-tech.pro/UNF/odata/standard.odata/Catalog_Контрагенты(guid'{cat_id}')?"
|
||||
+ "&".join([f"{p}={params[p]}" for p in params])
|
||||
)
|
||||
logger.info(remote_url)
|
||||
data = requests.get(remote_url, headers={"Authorization": settings.ODATA_AUTH})
|
||||
try:
|
||||
parsed_data = data.json()
|
||||
return Response(parsed_data)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
|
||||
def get_depth_cat(id):
|
||||
params = {
|
||||
"$format": "json",
|
||||
"$select": ",".join(["Description", "Ref_Key", "Parent_Key"]),
|
||||
"$filter": f"Parent_Key eq guid'{id}'",
|
||||
}
|
||||
remote_url = (
|
||||
"https://1c.svs-tech.pro/UNF/odata/standard.odata/Catalog_КатегорииНоменклатуры?"
|
||||
+ "&".join([f"{p}={params[p]}" for p in params])
|
||||
)
|
||||
data = requests.get(remote_url, headers={"Authorization": settings.ODATA_AUTH})
|
||||
parsed_data = data.json()
|
||||
return parsed_data["value"]
|
||||
|
||||
|
||||
class InventoryItemViewSet(viewsets.ModelViewSet):
|
||||
queryset = InventoryItem.objects.all()
|
||||
serializer_class = InventorySerializer
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = InventoryItem.objects.all()
|
||||
partner = self.request.query_params.get("partner_id")
|
||||
if partner is not None:
|
||||
queryset = queryset.filter(partner=partner)
|
||||
return queryset
|
||||
|
||||
def create(self, request, **kwargs):
|
||||
data = request.data
|
||||
|
||||
# check if partner exist
|
||||
if Partner.objects.filter(external_id=data["partner"]).exists():
|
||||
partner_object = Partner.objects.get(external_id=data["partner"])
|
||||
else:
|
||||
partner_object = Partner.objects.create(
|
||||
external_id=data["partner"],
|
||||
name=data["partner_name"],
|
||||
)
|
||||
partner_serializer = PartnerSerializer(partner_object, many=False)
|
||||
|
||||
inventory_object = InventoryItem.objects.create(
|
||||
partner=partner_object,
|
||||
name=f"{data['partner_name']} {datetime.datetime.now()}",
|
||||
)
|
||||
inventory_serializer = InventorySerializer(inventory_object, many=False)
|
||||
|
||||
return Response(
|
||||
{
|
||||
"partner": partner_serializer.data,
|
||||
"inventory": inventory_serializer.data,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ElementViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
API endpoint that allows elements to be viewed or edited.
|
||||
"""
|
||||
|
||||
queryset = Element.objects.all()
|
||||
serializer_class = ElementSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = Element.objects.all()
|
||||
inventory = self.request.query_params.get("inventory_id")
|
||||
if inventory is not None:
|
||||
queryset = queryset.filter(inventory=inventory)
|
||||
return queryset
|
||||
|
||||
def create(self, request, **kwargs):
|
||||
data = request.data
|
||||
|
||||
# check if partner exist
|
||||
if Partner.objects.filter(external_id=data["partner"]).exists():
|
||||
partner_object = Partner.objects.get(external_id=data["partner"])
|
||||
else:
|
||||
partner_object = Partner.objects.create(
|
||||
external_id=data["partner"],
|
||||
name=data["partner_name"],
|
||||
)
|
||||
partner_serializer = PartnerSerializer(partner_object, many=False)
|
||||
|
||||
# check if inventory exist
|
||||
if (
|
||||
"inventory"
|
||||
in data
|
||||
# and InventoryItem.objects.filter(id=data["inventory"]).exists()
|
||||
):
|
||||
inventory_object = InventoryItem.objects.get(id=data["inventory"])
|
||||
else:
|
||||
inventory_object = InventoryItem.objects.create(
|
||||
partner=partner_object,
|
||||
name=f"{data['partner_name']} {datetime.datetime.now()}",
|
||||
)
|
||||
inventory_serializer = InventorySerializer(inventory_object, many=False)
|
||||
|
||||
element_data = {
|
||||
"inventory": inventory_object.id,
|
||||
"external_id": data["element"],
|
||||
"element_id": data["element_id"],
|
||||
}
|
||||
if "element_additional_data" in data:
|
||||
element_data["additional_text"] = data["element_additional_data"]
|
||||
element_serializer = ElementSerializer(data=element_data, many=False)
|
||||
if element_serializer.is_valid():
|
||||
element_data["inventory"] = inventory_object
|
||||
Element.objects.create(**element_data)
|
||||
return Response(
|
||||
{
|
||||
"partner": partner_serializer.data,
|
||||
"inventory": inventory_serializer.data,
|
||||
"element": element_serializer.data,
|
||||
}
|
||||
)
|
||||
else:
|
||||
return Response(
|
||||
element_serializer.errors, status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
||||
)
|
||||
|
||||
@action(
|
||||
detail=False,
|
||||
methods=["get"],
|
||||
url_path=r"external_categories",
|
||||
)
|
||||
def get_remote_categories(self, request, cat_id=None):
|
||||
try:
|
||||
categories = get_depth_cat("87e91e07-7e10-11ee-ab5a-a47a2bd811cb")
|
||||
categories.extend(get_depth_cat("20e1e6f6-a575-11ee-ab60-ec3c37e2e642"))
|
||||
categories.extend(get_depth_cat('1f89290b-ffaf-11ed-ab4e-e3e667c628bd'))
|
||||
return Response(categories)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
@action(
|
||||
detail=False,
|
||||
methods=["get"],
|
||||
url_path=r"external_categories/(?P<cat_id>[^/.]+)",
|
||||
)
|
||||
def get_remote_categories_child(self, request, cat_id=None):
|
||||
try:
|
||||
categories = get_depth_cat(cat_id)
|
||||
return Response(categories)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
@action(detail=False, methods=["get"], url_path=r"external/(?P<cat_id>[^/.]+)")
|
||||
def get_remote_element(self, request, pk=None, cat_id=None):
|
||||
try:
|
||||
params = {
|
||||
"$format": "json",
|
||||
"$select": ",".join(["Description", "Ref_Key", "Parent_Key"]),
|
||||
"$filter": f"КатегорияНоменклатуры_Key eq guid'{cat_id}'",
|
||||
}
|
||||
remote_url = (
|
||||
"https://1c.svs-tech.pro/UNF/odata/standard.odata/Catalog_Номенклатура?"
|
||||
+ "&".join([f"{p}={params[p]}" for p in params])
|
||||
)
|
||||
data = requests.get(
|
||||
remote_url, headers={"Authorization": settings.ODATA_AUTH}
|
||||
)
|
||||
parsed_data = data.json()
|
||||
return Response(parsed_data["value"])
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
@action(detail=False, methods=["get"], url_path=r"external/id/(?P<cat_id>[^/.]+)")
|
||||
def get_remote_element_by_id(self, request, pk=None, cat_id=None):
|
||||
try:
|
||||
params = {
|
||||
"$format": "json",
|
||||
"$select": ",".join(["Description", "Ref_Key", "Parent_Key"]),
|
||||
}
|
||||
remote_url = (
|
||||
f"https://1c.svs-tech.pro/UNF/odata/standard.odata/Catalog_Номенклатура(guid'{cat_id}')?"
|
||||
+ "&".join([f"{p}={params[p]}" for p in params])
|
||||
)
|
||||
data = requests.get(
|
||||
remote_url, headers={"Authorization": settings.ODATA_AUTH}
|
||||
)
|
||||
parsed_data = data.json()
|
||||
return Response(parsed_data)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
@ -1,5 +1,55 @@
|
|||
# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "anyio"
|
||||
version = "4.4.0"
|
||||
description = "High level compatibility layer for multiple asynchronous event loop implementations"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"},
|
||||
{file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""}
|
||||
idna = ">=2.8"
|
||||
sniffio = ">=1.1"
|
||||
typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""}
|
||||
|
||||
[package.extras]
|
||||
doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
|
||||
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
|
||||
trio = ["trio (>=0.23)"]
|
||||
|
||||
[[package]]
|
||||
name = "apscheduler"
|
||||
version = "3.10.4"
|
||||
description = "In-process task scheduler with Cron-like capabilities"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "APScheduler-3.10.4-py3-none-any.whl", hash = "sha256:fb91e8a768632a4756a585f79ec834e0e27aad5860bac7eaa523d9ccefd87661"},
|
||||
{file = "APScheduler-3.10.4.tar.gz", hash = "sha256:e6df071b27d9be898e486bc7940a7be50b4af2e9da7c08f0744a96d4bd4cef4a"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
pytz = "*"
|
||||
six = ">=1.4.0"
|
||||
tzlocal = ">=2.0,<3.dev0 || >=4.dev0"
|
||||
|
||||
[package.extras]
|
||||
doc = ["sphinx", "sphinx-rtd-theme"]
|
||||
gevent = ["gevent"]
|
||||
mongodb = ["pymongo (>=3.0)"]
|
||||
redis = ["redis (>=3.0)"]
|
||||
rethinkdb = ["rethinkdb (>=2.4.0)"]
|
||||
sqlalchemy = ["sqlalchemy (>=1.4)"]
|
||||
testing = ["pytest", "pytest-asyncio", "pytest-cov", "pytest-tornado5"]
|
||||
tornado = ["tornado (>=4.3)"]
|
||||
twisted = ["twisted"]
|
||||
zookeeper = ["kazoo"]
|
||||
|
||||
[[package]]
|
||||
name = "asgiref"
|
||||
version = "3.8.1"
|
||||
|
@ -17,6 +67,116 @@ typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""}
|
|||
[package.extras]
|
||||
tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2024.2.2"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"},
|
||||
{file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "3.3.2"
|
||||
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
||||
optional = false
|
||||
python-versions = ">=3.7.0"
|
||||
files = [
|
||||
{file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
|
||||
{file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
|
@ -48,6 +208,35 @@ tzdata = {version = "*", markers = "sys_platform == \"win32\""}
|
|||
argon2 = ["argon2-cffi (>=19.1.0)"]
|
||||
bcrypt = ["bcrypt"]
|
||||
|
||||
[[package]]
|
||||
name = "django-cors-headers"
|
||||
version = "4.3.1"
|
||||
description = "django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS)."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "django-cors-headers-4.3.1.tar.gz", hash = "sha256:0bf65ef45e606aff1994d35503e6b677c0b26cafff6506f8fd7187f3be840207"},
|
||||
{file = "django_cors_headers-4.3.1-py3-none-any.whl", hash = "sha256:0b1fd19297e37417fc9f835d39e45c8c642938ddba1acce0c1753d3edef04f36"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
asgiref = ">=3.6"
|
||||
Django = ">=3.2"
|
||||
|
||||
[[package]]
|
||||
name = "django-filter"
|
||||
version = "24.2"
|
||||
description = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "django-filter-24.2.tar.gz", hash = "sha256:48e5fc1da3ccd6ca0d5f9bb550973518ce977a4edde9d2a8a154a7f4f0b9f96e"},
|
||||
{file = "django_filter-24.2-py3-none-any.whl", hash = "sha256:df2ee9857e18d38bed203c8745f62a803fa0f31688c9fe6f8e868120b1848e48"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
Django = ">=4.2"
|
||||
|
||||
[[package]]
|
||||
name = "djangorestframework"
|
||||
version = "3.15.1"
|
||||
|
@ -62,6 +251,102 @@ files = [
|
|||
[package.dependencies]
|
||||
django = ">=3.0"
|
||||
|
||||
[[package]]
|
||||
name = "exceptiongroup"
|
||||
version = "1.2.1"
|
||||
description = "Backport of PEP 654 (exception groups)"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"},
|
||||
{file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
test = ["pytest (>=6)"]
|
||||
|
||||
[[package]]
|
||||
name = "h11"
|
||||
version = "0.14.0"
|
||||
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
|
||||
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpcore"
|
||||
version = "1.0.5"
|
||||
description = "A minimal low-level HTTP client."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"},
|
||||
{file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
certifi = "*"
|
||||
h11 = ">=0.13,<0.15"
|
||||
|
||||
[package.extras]
|
||||
asyncio = ["anyio (>=4.0,<5.0)"]
|
||||
http2 = ["h2 (>=3,<5)"]
|
||||
socks = ["socksio (==1.*)"]
|
||||
trio = ["trio (>=0.22.0,<0.26.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "httpx"
|
||||
version = "0.27.0"
|
||||
description = "The next generation HTTP client."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"},
|
||||
{file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
anyio = "*"
|
||||
certifi = "*"
|
||||
httpcore = "==1.*"
|
||||
idna = "*"
|
||||
sniffio = "*"
|
||||
|
||||
[package.extras]
|
||||
brotli = ["brotli", "brotlicffi"]
|
||||
cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"]
|
||||
http2 = ["h2 (>=3,<5)"]
|
||||
socks = ["socksio (==1.*)"]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.7"
|
||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
files = [
|
||||
{file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
|
||||
{file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markdown"
|
||||
version = "3.6"
|
||||
description = "Python implementation of John Gruber's Markdown."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "Markdown-3.6-py3-none-any.whl", hash = "sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f"},
|
||||
{file = "Markdown-3.6.tar.gz", hash = "sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"]
|
||||
testing = ["coverage", "pyyaml"]
|
||||
|
||||
[[package]]
|
||||
name = "mslex"
|
||||
version = "1.2.0"
|
||||
|
@ -73,6 +358,92 @@ files = [
|
|||
{file = "mslex-1.2.0.tar.gz", hash = "sha256:79e2abc5a129dd71cdde58a22a2039abb7fa8afcbac498b723ba6e9b9fbacc14"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pillow"
|
||||
version = "10.3.0"
|
||||
description = "Python Imaging Library (Fork)"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pillow-10.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:90b9e29824800e90c84e4022dd5cc16eb2d9605ee13f05d47641eb183cd73d45"},
|
||||
{file = "pillow-10.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a2c405445c79c3f5a124573a051062300936b0281fee57637e706453e452746c"},
|
||||
{file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78618cdbccaa74d3f88d0ad6cb8ac3007f1a6fa5c6f19af64b55ca170bfa1edf"},
|
||||
{file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261ddb7ca91fcf71757979534fb4c128448b5b4c55cb6152d280312062f69599"},
|
||||
{file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ce49c67f4ea0609933d01c0731b34b8695a7a748d6c8d186f95e7d085d2fe475"},
|
||||
{file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b14f16f94cbc61215115b9b1236f9c18403c15dd3c52cf629072afa9d54c1cbf"},
|
||||
{file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d33891be6df59d93df4d846640f0e46f1a807339f09e79a8040bc887bdcd7ed3"},
|
||||
{file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b50811d664d392f02f7761621303eba9d1b056fb1868c8cdf4231279645c25f5"},
|
||||
{file = "pillow-10.3.0-cp310-cp310-win32.whl", hash = "sha256:ca2870d5d10d8726a27396d3ca4cf7976cec0f3cb706debe88e3a5bd4610f7d2"},
|
||||
{file = "pillow-10.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:f0d0591a0aeaefdaf9a5e545e7485f89910c977087e7de2b6c388aec32011e9f"},
|
||||
{file = "pillow-10.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:ccce24b7ad89adb5a1e34a6ba96ac2530046763912806ad4c247356a8f33a67b"},
|
||||
{file = "pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795"},
|
||||
{file = "pillow-10.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57"},
|
||||
{file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdcbb4068117dfd9ce0138d068ac512843c52295ed996ae6dd1faf537b6dbc27"},
|
||||
{file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9797a6c8fe16f25749b371c02e2ade0efb51155e767a971c61734b1bf6293994"},
|
||||
{file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9e91179a242bbc99be65e139e30690e081fe6cb91a8e77faf4c409653de39451"},
|
||||
{file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd"},
|
||||
{file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:81d09caa7b27ef4e61cb7d8fbf1714f5aec1c6b6c5270ee53504981e6e9121ad"},
|
||||
{file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:048ad577748b9fa4a99a0548c64f2cb8d672d5bf2e643a739ac8faff1164238c"},
|
||||
{file = "pillow-10.3.0-cp311-cp311-win32.whl", hash = "sha256:7161ec49ef0800947dc5570f86568a7bb36fa97dd09e9827dc02b718c5643f09"},
|
||||
{file = "pillow-10.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d"},
|
||||
{file = "pillow-10.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:4e6f7d1c414191c1199f8996d3f2282b9ebea0945693fb67392c75a3a320941f"},
|
||||
{file = "pillow-10.3.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:e46f38133e5a060d46bd630faa4d9fa0202377495df1f068a8299fd78c84de84"},
|
||||
{file = "pillow-10.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:50b8eae8f7334ec826d6eeffaeeb00e36b5e24aa0b9df322c247539714c6df19"},
|
||||
{file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d3bea1c75f8c53ee4d505c3e67d8c158ad4df0d83170605b50b64025917f338"},
|
||||
{file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19aeb96d43902f0a783946a0a87dbdad5c84c936025b8419da0a0cd7724356b1"},
|
||||
{file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:74d28c17412d9caa1066f7a31df8403ec23d5268ba46cd0ad2c50fb82ae40462"},
|
||||
{file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ff61bfd9253c3915e6d41c651d5f962da23eda633cf02262990094a18a55371a"},
|
||||
{file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d886f5d353333b4771d21267c7ecc75b710f1a73d72d03ca06df49b09015a9ef"},
|
||||
{file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b5ec25d8b17217d635f8935dbc1b9aa5907962fae29dff220f2659487891cd3"},
|
||||
{file = "pillow-10.3.0-cp312-cp312-win32.whl", hash = "sha256:51243f1ed5161b9945011a7360e997729776f6e5d7005ba0c6879267d4c5139d"},
|
||||
{file = "pillow-10.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:412444afb8c4c7a6cc11a47dade32982439925537e483be7c0ae0cf96c4f6a0b"},
|
||||
{file = "pillow-10.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:798232c92e7665fe82ac085f9d8e8ca98826f8e27859d9a96b41d519ecd2e49a"},
|
||||
{file = "pillow-10.3.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:4eaa22f0d22b1a7e93ff0a596d57fdede2e550aecffb5a1ef1106aaece48e96b"},
|
||||
{file = "pillow-10.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cd5e14fbf22a87321b24c88669aad3a51ec052eb145315b3da3b7e3cc105b9a2"},
|
||||
{file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1530e8f3a4b965eb6a7785cf17a426c779333eb62c9a7d1bbcf3ffd5bf77a4aa"},
|
||||
{file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d512aafa1d32efa014fa041d38868fda85028e3f930a96f85d49c7d8ddc0383"},
|
||||
{file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:339894035d0ede518b16073bdc2feef4c991ee991a29774b33e515f1d308e08d"},
|
||||
{file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:aa7e402ce11f0885305bfb6afb3434b3cd8f53b563ac065452d9d5654c7b86fd"},
|
||||
{file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0ea2a783a2bdf2a561808fe4a7a12e9aa3799b701ba305de596bc48b8bdfce9d"},
|
||||
{file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c78e1b00a87ce43bb37642c0812315b411e856a905d58d597750eb79802aaaa3"},
|
||||
{file = "pillow-10.3.0-cp38-cp38-win32.whl", hash = "sha256:72d622d262e463dfb7595202d229f5f3ab4b852289a1cd09650362db23b9eb0b"},
|
||||
{file = "pillow-10.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:2034f6759a722da3a3dbd91a81148cf884e91d1b747992ca288ab88c1de15999"},
|
||||
{file = "pillow-10.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2ed854e716a89b1afcedea551cd85f2eb2a807613752ab997b9974aaa0d56936"},
|
||||
{file = "pillow-10.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dc1a390a82755a8c26c9964d457d4c9cbec5405896cba94cf51f36ea0d855002"},
|
||||
{file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4203efca580f0dd6f882ca211f923168548f7ba334c189e9eab1178ab840bf60"},
|
||||
{file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3102045a10945173d38336f6e71a8dc71bcaeed55c3123ad4af82c52807b9375"},
|
||||
{file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:6fb1b30043271ec92dc65f6d9f0b7a830c210b8a96423074b15c7bc999975f57"},
|
||||
{file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:1dfc94946bc60ea375cc39cff0b8da6c7e5f8fcdc1d946beb8da5c216156ddd8"},
|
||||
{file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b09b86b27a064c9624d0a6c54da01c1beaf5b6cadfa609cf63789b1d08a797b9"},
|
||||
{file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d3b2348a78bc939b4fed6552abfd2e7988e0f81443ef3911a4b8498ca084f6eb"},
|
||||
{file = "pillow-10.3.0-cp39-cp39-win32.whl", hash = "sha256:45ebc7b45406febf07fef35d856f0293a92e7417ae7933207e90bf9090b70572"},
|
||||
{file = "pillow-10.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:0ba26351b137ca4e0db0342d5d00d2e355eb29372c05afd544ebf47c0956ffeb"},
|
||||
{file = "pillow-10.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:50fd3f6b26e3441ae07b7c979309638b72abc1a25da31a81a7fbd9495713ef4f"},
|
||||
{file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:6b02471b72526ab8a18c39cb7967b72d194ec53c1fd0a70b050565a0f366d355"},
|
||||
{file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8ab74c06ffdab957d7670c2a5a6e1a70181cd10b727cd788c4dd9005b6a8acd9"},
|
||||
{file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:048eeade4c33fdf7e08da40ef402e748df113fd0b4584e32c4af74fe78baaeb2"},
|
||||
{file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2ec1e921fd07c7cda7962bad283acc2f2a9ccc1b971ee4b216b75fad6f0463"},
|
||||
{file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c8e73e99da7db1b4cad7f8d682cf6abad7844da39834c288fbfa394a47bbced"},
|
||||
{file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:16563993329b79513f59142a6b02055e10514c1a8e86dca8b48a893e33cf91e3"},
|
||||
{file = "pillow-10.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:dd78700f5788ae180b5ee8902c6aea5a5726bac7c364b202b4b3e3ba2d293170"},
|
||||
{file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:aff76a55a8aa8364d25400a210a65ff59d0168e0b4285ba6bf2bd83cf675ba32"},
|
||||
{file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b7bc2176354defba3edc2b9a777744462da2f8e921fbaf61e52acb95bafa9828"},
|
||||
{file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:793b4e24db2e8742ca6423d3fde8396db336698c55cd34b660663ee9e45ed37f"},
|
||||
{file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d93480005693d247f8346bc8ee28c72a2191bdf1f6b5db469c096c0c867ac015"},
|
||||
{file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83341b89884e2b2e55886e8fbbf37c3fa5efd6c8907124aeb72f285ae5696e5"},
|
||||
{file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a1d1915db1a4fdb2754b9de292642a39a7fb28f1736699527bb649484fb966a"},
|
||||
{file = "pillow-10.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a0eaa93d054751ee9964afa21c06247779b90440ca41d184aeb5d410f20ff591"},
|
||||
{file = "pillow-10.3.0.tar.gz", hash = "sha256:9d2455fbf44c914840c793e89aa82d0e1763a14253a000743719ae5946814b2d"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"]
|
||||
fpx = ["olefile"]
|
||||
mic = ["olefile"]
|
||||
tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]
|
||||
typing = ["typing-extensions"]
|
||||
xmp = ["defusedxml"]
|
||||
|
||||
[[package]]
|
||||
name = "psutil"
|
||||
version = "5.9.8"
|
||||
|
@ -101,6 +472,182 @@ files = [
|
|||
[package.extras]
|
||||
test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"]
|
||||
|
||||
[[package]]
|
||||
name = "psycopg2-binary"
|
||||
version = "2.9.9"
|
||||
description = "psycopg2 - Python-PostgreSQL Database Adapter"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "psycopg2-binary-2.9.9.tar.gz", hash = "sha256:7f01846810177d829c7692f1f5ada8096762d9172af1b1a28d4ab5b77c923c1c"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c2470da5418b76232f02a2fcd2229537bb2d5a7096674ce61859c3229f2eb202"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c6af2a6d4b7ee9615cbb162b0738f6e1fd1f5c3eda7e5da17861eacf4c717ea7"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75723c3c0fbbf34350b46a3199eb50638ab22a0228f93fb472ef4d9becc2382b"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83791a65b51ad6ee6cf0845634859d69a038ea9b03d7b26e703f94c7e93dbcf9"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ef4854e82c09e84cc63084a9e4ccd6d9b154f1dbdd283efb92ecd0b5e2b8c84"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed1184ab8f113e8d660ce49a56390ca181f2981066acc27cf637d5c1e10ce46e"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d2997c458c690ec2bc6b0b7ecbafd02b029b7b4283078d3b32a852a7ce3ddd98"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b58b4710c7f4161b5e9dcbe73bb7c62d65670a87df7bcce9e1faaad43e715245"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0c009475ee389757e6e34611d75f6e4f05f0cf5ebb76c6037508318e1a1e0d7e"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8dbf6d1bc73f1d04ec1734bae3b4fb0ee3cb2a493d35ede9badbeb901fb40f6f"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-win32.whl", hash = "sha256:3f78fd71c4f43a13d342be74ebbc0666fe1f555b8837eb113cb7416856c79682"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-win_amd64.whl", hash = "sha256:876801744b0dee379e4e3c38b76fc89f88834bb15bf92ee07d94acd06ec890a0"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ee825e70b1a209475622f7f7b776785bd68f34af6e7a46e2e42f27b659b5bc26"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1ea665f8ce695bcc37a90ee52de7a7980be5161375d42a0b6c6abedbf0d81f0f"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:143072318f793f53819048fdfe30c321890af0c3ec7cb1dfc9cc87aa88241de2"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c332c8d69fb64979ebf76613c66b985414927a40f8defa16cf1bc028b7b0a7b0"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7fc5a5acafb7d6ccca13bfa8c90f8c51f13d8fb87d95656d3950f0158d3ce53"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:977646e05232579d2e7b9c59e21dbe5261f403a88417f6a6512e70d3f8a046be"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b6356793b84728d9d50ead16ab43c187673831e9d4019013f1402c41b1db9b27"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bc7bb56d04601d443f24094e9e31ae6deec9ccb23581f75343feebaf30423359"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:77853062a2c45be16fd6b8d6de2a99278ee1d985a7bd8b103e97e41c034006d2"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:78151aa3ec21dccd5cdef6c74c3e73386dcdfaf19bced944169697d7ac7482fc"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-win32.whl", hash = "sha256:dc4926288b2a3e9fd7b50dc6a1909a13bbdadfc67d93f3374d984e56f885579d"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-win_amd64.whl", hash = "sha256:b76bedd166805480ab069612119ea636f5ab8f8771e640ae103e05a4aae3e417"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8532fd6e6e2dc57bcb3bc90b079c60de896d2128c5d9d6f24a63875a95a088cf"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0605eaed3eb239e87df0d5e3c6489daae3f7388d455d0c0b4df899519c6a38d"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f8544b092a29a6ddd72f3556a9fcf249ec412e10ad28be6a0c0d948924f2212"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d423c8d8a3c82d08fe8af900ad5b613ce3632a1249fd6a223941d0735fce493"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e5afae772c00980525f6d6ecf7cbca55676296b580c0e6abb407f15f3706996"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e6f98446430fdf41bd36d4faa6cb409f5140c1c2cf58ce0bbdaf16af7d3f119"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c77e3d1862452565875eb31bdb45ac62502feabbd53429fdc39a1cc341d681ba"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:cb16c65dcb648d0a43a2521f2f0a2300f40639f6f8c1ecbc662141e4e3e1ee07"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:911dda9c487075abd54e644ccdf5e5c16773470a6a5d3826fda76699410066fb"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:57fede879f08d23c85140a360c6a77709113efd1c993923c59fde17aa27599fe"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-win32.whl", hash = "sha256:64cf30263844fa208851ebb13b0732ce674d8ec6a0c86a4e160495d299ba3c93"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-win_amd64.whl", hash = "sha256:81ff62668af011f9a48787564ab7eded4e9fb17a4a6a74af5ffa6a457400d2ab"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2293b001e319ab0d869d660a704942c9e2cce19745262a8aba2115ef41a0a42a"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03ef7df18daf2c4c07e2695e8cfd5ee7f748a1d54d802330985a78d2a5a6dca9"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a602ea5aff39bb9fac6308e9c9d82b9a35c2bf288e184a816002c9fae930b77"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8359bf4791968c5a78c56103702000105501adb557f3cf772b2c207284273984"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:275ff571376626195ab95a746e6a04c7df8ea34638b99fc11160de91f2fef503"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f9b5571d33660d5009a8b3c25dc1db560206e2d2f89d3df1cb32d72c0d117d52"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:420f9bbf47a02616e8554e825208cb947969451978dceb77f95ad09c37791dae"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:4154ad09dac630a0f13f37b583eae260c6aa885d67dfbccb5b02c33f31a6d420"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a148c5d507bb9b4f2030a2025c545fccb0e1ef317393eaba42e7eabd28eb6041"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-win32.whl", hash = "sha256:68fc1f1ba168724771e38bee37d940d2865cb0f562380a1fb1ffb428b75cb692"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-win_amd64.whl", hash = "sha256:281309265596e388ef483250db3640e5f414168c5a67e9c665cafce9492eda2f"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:60989127da422b74a04345096c10d416c2b41bd7bf2a380eb541059e4e999980"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:246b123cc54bb5361588acc54218c8c9fb73068bf227a4a531d8ed56fa3ca7d6"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34eccd14566f8fe14b2b95bb13b11572f7c7d5c36da61caf414d23b91fcc5d94"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18d0ef97766055fec15b5de2c06dd8e7654705ce3e5e5eed3b6651a1d2a9a152"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d3f82c171b4ccd83bbaf35aa05e44e690113bd4f3b7b6cc54d2219b132f3ae55"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ead20f7913a9c1e894aebe47cccf9dc834e1618b7aa96155d2091a626e59c972"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ca49a8119c6cbd77375ae303b0cfd8c11f011abbbd64601167ecca18a87e7cdd"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:323ba25b92454adb36fa425dc5cf6f8f19f78948cbad2e7bc6cdf7b0d7982e59"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:1236ed0952fbd919c100bc839eaa4a39ebc397ed1c08a97fc45fee2a595aa1b3"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:729177eaf0aefca0994ce4cffe96ad3c75e377c7b6f4efa59ebf003b6d398716"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-win32.whl", hash = "sha256:804d99b24ad523a1fe18cc707bf741670332f7c7412e9d49cb5eab67e886b9b5"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-win_amd64.whl", hash = "sha256:a6cdcc3ede532f4a4b96000b6362099591ab4a3e913d70bcbac2b56c872446f7"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:72dffbd8b4194858d0941062a9766f8297e8868e1dd07a7b36212aaa90f49472"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:30dcc86377618a4c8f3b72418df92e77be4254d8f89f14b8e8f57d6d43603c0f"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31a34c508c003a4347d389a9e6fcc2307cc2150eb516462a7a17512130de109e"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15208be1c50b99203fe88d15695f22a5bed95ab3f84354c494bcb1d08557df67"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1873aade94b74715be2246321c8650cabf5a0d098a95bab81145ffffa4c13876"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a58c98a7e9c021f357348867f537017057c2ed7f77337fd914d0bedb35dace7"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4686818798f9194d03c9129a4d9a702d9e113a89cb03bffe08c6cf799e053291"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ebdc36bea43063116f0486869652cb2ed7032dbc59fbcb4445c4862b5c1ecf7f"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ca08decd2697fdea0aea364b370b1249d47336aec935f87b8bbfd7da5b2ee9c1"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ac05fb791acf5e1a3e39402641827780fe44d27e72567a000412c648a85ba860"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-win32.whl", hash = "sha256:9dba73be7305b399924709b91682299794887cbbd88e38226ed9f6712eabee90"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-win_amd64.whl", hash = "sha256:f7ae5d65ccfbebdfa761585228eb4d0df3a8b15cfb53bd953e713e09fbb12957"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "1.0.1"
|
||||
description = "Read key-value pairs from a .env file and set them as environment variables"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"},
|
||||
{file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
cli = ["click (>=5.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "python-telegram-bot"
|
||||
version = "21.3"
|
||||
description = "We have made you a wrapper you can't refuse"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "python-telegram-bot-21.3.tar.gz", hash = "sha256:1be3c8b6f2b7354418109daa3f23c522e82ed22e7fc904346bee0c7b4aab52ae"},
|
||||
{file = "python_telegram_bot-21.3-py3-none-any.whl", hash = "sha256:8f575e6da903edd1e78967b5b481455ee6b27f2804d2384029177eab165f2e93"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
APScheduler = {version = ">=3.10.4,<3.11.0", optional = true, markers = "extra == \"job-queue\""}
|
||||
httpx = ">=0.27,<1.0"
|
||||
pytz = {version = ">=2018.6", optional = true, markers = "extra == \"job-queue\""}
|
||||
|
||||
[package.extras]
|
||||
all = ["APScheduler (>=3.10.4,<3.11.0)", "aiolimiter (>=1.1.0,<1.2.0)", "cachetools (>=5.3.3,<5.4.0)", "cryptography (>=39.0.1)", "httpx[http2]", "httpx[socks]", "pytz (>=2018.6)", "tornado (>=6.4,<7.0)"]
|
||||
callback-data = ["cachetools (>=5.3.3,<5.4.0)"]
|
||||
ext = ["APScheduler (>=3.10.4,<3.11.0)", "aiolimiter (>=1.1.0,<1.2.0)", "cachetools (>=5.3.3,<5.4.0)", "pytz (>=2018.6)", "tornado (>=6.4,<7.0)"]
|
||||
http2 = ["httpx[http2]"]
|
||||
job-queue = ["APScheduler (>=3.10.4,<3.11.0)", "pytz (>=2018.6)"]
|
||||
passport = ["cryptography (>=39.0.1)"]
|
||||
rate-limiter = ["aiolimiter (>=1.1.0,<1.2.0)"]
|
||||
socks = ["httpx[socks]"]
|
||||
webhooks = ["tornado (>=6.4,<7.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "pytz"
|
||||
version = "2024.1"
|
||||
description = "World timezone definitions, modern and historical"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"},
|
||||
{file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.3"
|
||||
description = "Python HTTP for Humans."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
|
||||
{file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
certifi = ">=2017.4.17"
|
||||
charset-normalizer = ">=2,<4"
|
||||
idna = ">=2.5,<4"
|
||||
urllib3 = ">=1.21.1,<3"
|
||||
|
||||
[package.extras]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
||||
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
version = "1.16.0"
|
||||
description = "Python 2 and 3 compatibility utilities"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
files = [
|
||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sniffio"
|
||||
version = "1.3.1"
|
||||
description = "Sniff out which async library your code is running under"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
|
||||
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlparse"
|
||||
version = "0.5.0"
|
||||
|
@ -166,7 +713,41 @@ files = [
|
|||
{file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tzlocal"
|
||||
version = "5.2"
|
||||
description = "tzinfo object for the local timezone"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "tzlocal-5.2-py3-none-any.whl", hash = "sha256:49816ef2fe65ea8ac19d19aa7a1ae0551c834303d5014c6d5a62e4cbda8047b8"},
|
||||
{file = "tzlocal-5.2.tar.gz", hash = "sha256:8d399205578f1a9342816409cc1e46a93ebd5755e39ea2d85334bea911bf0e6e"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
tzdata = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
|
||||
[package.extras]
|
||||
devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.2.1"
|
||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
|
||||
{file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
|
||||
h2 = ["h2 (>=4,<5)"]
|
||||
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||
zstd = ["zstandard (>=0.18.0)"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.10"
|
||||
content-hash = "6efdb9c4415a13fd7937a0c572c15bd548446e6ee2d18c81c72c23d75842af08"
|
||||
content-hash = "b0a8df55d3a7a429a89e692c2f74d3f41144a44fb1da3b108105ac9353eab7db"
|
||||
|
|
|
@ -2,14 +2,21 @@
|
|||
name = "back"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
authors = ["k.mikhailova@svs-tech.pro"]
|
||||
authors = ["Ksenia Miqhailova <k.mikhailova@svs-tech.pro>"]
|
||||
readme = "readme.md"
|
||||
package-mode = false
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.10"
|
||||
Django = "^5.0.6"
|
||||
djangorestframework = "^3.15.1"
|
||||
psycopg2-binary = "^2.9.9"
|
||||
markdown = "^3.6"
|
||||
django-filter = "^24.2"
|
||||
pillow = "^10.3.0"
|
||||
python-dotenv = "^1.0.1"
|
||||
requests = "^2.32.2"
|
||||
django-cors-headers = "^4.3.1"
|
||||
python-telegram-bot = {extras = ["job-queue"], version = "^21.3"}
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
taskipy = "^1.12.2"
|
||||
|
@ -20,4 +27,4 @@ build-backend = "poetry.core.masonry.api"
|
|||
|
||||
[tool.taskipy.tasks]
|
||||
migrate = "python manage.py makemigrations && python manage.py migrate"
|
||||
server = "python manage.py runserver"
|
||||
server = "python manage.py runserver 0.0.0.0:8000"
|
|
@ -0,0 +1,38 @@
|
|||
asgiref==3.8.1 ; python_version >= "3.10" and python_version < "4.0" \
|
||||
--hash=sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47 \
|
||||
--hash=sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590
|
||||
django-filter==24.2 ; python_version >= "3.10" and python_version < "4.0" \
|
||||
--hash=sha256:48e5fc1da3ccd6ca0d5f9bb550973518ce977a4edde9d2a8a154a7f4f0b9f96e \
|
||||
--hash=sha256:df2ee9857e18d38bed203c8745f62a803fa0f31688c9fe6f8e868120b1848e48
|
||||
django==5.0.6 ; python_version >= "3.10" and python_version < "4.0" \
|
||||
--hash=sha256:8363ac062bb4ef7c3f12d078f6fa5d154031d129a15170a1066412af49d30905 \
|
||||
--hash=sha256:ff1b61005004e476e0aeea47c7f79b85864c70124030e95146315396f1e7951f
|
||||
djangorestframework==3.15.1 ; python_version >= "3.10" and python_version < "4.0" \
|
||||
--hash=sha256:3ccc0475bce968608cf30d07fb17d8e52d1d7fc8bfe779c905463200750cbca6 \
|
||||
--hash=sha256:f88fad74183dfc7144b2756d0d2ac716ea5b4c7c9840995ac3bfd8ec034333c1
|
||||
markdown==3.6 ; python_version >= "3.10" and python_version < "4.0" \
|
||||
--hash=sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f \
|
||||
--hash=sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224
|
||||
psycopg2==2.9.9 ; python_version >= "3.10" and python_version < "4.0" \
|
||||
--hash=sha256:121081ea2e76729acfb0673ff33755e8703d45e926e416cb59bae3a86c6a4981 \
|
||||
--hash=sha256:38a8dcc6856f569068b47de286b472b7c473ac7977243593a288ebce0dc89516 \
|
||||
--hash=sha256:426f9f29bde126913a20a96ff8ce7d73fd8a216cfb323b1f04da402d452853c3 \
|
||||
--hash=sha256:5e0d98cade4f0e0304d7d6f25bbfbc5bd186e07b38eac65379309c4ca3193efa \
|
||||
--hash=sha256:7e2dacf8b009a1c1e843b5213a87f7c544b2b042476ed7755be813eaf4e8347a \
|
||||
--hash=sha256:a7653d00b732afb6fc597e29c50ad28087dcb4fbfb28e86092277a559ae4e693 \
|
||||
--hash=sha256:ade01303ccf7ae12c356a5e10911c9e1c51136003a9a1d92f7aa9d010fb98372 \
|
||||
--hash=sha256:bac58c024c9922c23550af2a581998624d6e02350f4ae9c5f0bc642c633a2d5e \
|
||||
--hash=sha256:c92811b2d4c9b6ea0285942b2e7cac98a59e166d59c588fe5cfe1eda58e72d59 \
|
||||
--hash=sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156 \
|
||||
--hash=sha256:d735786acc7dd25815e89cc4ad529a43af779db2e25aa7c626de864127e5a024 \
|
||||
--hash=sha256:de80739447af31525feddeb8effd640782cf5998e1a4e9192ebdf829717e3913 \
|
||||
--hash=sha256:ff432630e510709564c01dafdbe996cb552e0b9f3f065eb89bdce5bd31fabf4c
|
||||
sqlparse==0.5.0 ; python_version >= "3.10" and python_version < "4.0" \
|
||||
--hash=sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93 \
|
||||
--hash=sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663
|
||||
typing-extensions==4.12.0 ; python_version >= "3.10" and python_version < "3.11" \
|
||||
--hash=sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8 \
|
||||
--hash=sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594
|
||||
tzdata==2024.1 ; python_version >= "3.10" and python_version < "4.0" and sys_platform == "win32" \
|
||||
--hash=sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd \
|
||||
--hash=sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252
|
|
@ -1,3 +1,5 @@
|
|||
from django.contrib import admin
|
||||
from .models import Item
|
||||
|
||||
# Register your models here.
|
||||
admin.site.register(Item)
|
|
@ -0,0 +1,62 @@
|
|||
from asgiref.sync import async_to_sync
|
||||
from django.apps import AppConfig
|
||||
import asyncio
|
||||
import threading
|
||||
import queue
|
||||
import time
|
||||
|
||||
|
||||
class TgBotClass(AppConfig):
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "tgbot"
|
||||
is_run = False
|
||||
app = None
|
||||
|
||||
update_queue = None
|
||||
my_queue = queue.Queue()
|
||||
|
||||
# @async_to_sync
|
||||
async def init_bot(self):
|
||||
from django.conf import settings
|
||||
from .tgbot import TgBotApp
|
||||
|
||||
tgbot = TgBotApp()
|
||||
app = await tgbot.init_tg()
|
||||
await tgbot.set_webhook(f"https://{settings.TGBOT['base_url']}/api/tgbot/")
|
||||
return app
|
||||
|
||||
async def some_function(self=None):
|
||||
# await TgBotClass.app.bot.get_me()
|
||||
while True:
|
||||
if not TgBotClass.my_queue.empty():
|
||||
item = TgBotClass.my_queue.get()
|
||||
try:
|
||||
await TgBotClass.app.process_update(item)
|
||||
except Exception as e:
|
||||
print('err')
|
||||
await TgBotClass.app.process_update(item)
|
||||
TgBotClass.my_queue.task_done()
|
||||
time.sleep(3)
|
||||
|
||||
async def some_callback():
|
||||
await TgBotClass.some_function()
|
||||
|
||||
def between_callback():
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
|
||||
loop.run_until_complete(TgBotClass.some_callback())
|
||||
loop.close()
|
||||
|
||||
def ready(self):
|
||||
import os
|
||||
|
||||
if os.environ.get("RUN_MAIN", None) != "true":
|
||||
return
|
||||
if TgBotClass.is_run:
|
||||
return
|
||||
TgBotClass.is_run = True
|
||||
TgBotClass.app = async_to_sync(self.init_bot, force_new_loop=True)()
|
||||
thread = threading.Thread(target=TgBotClass.between_callback)
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
|
@ -0,0 +1,8 @@
|
|||
from django.db import models
|
||||
|
||||
class Item(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=255)
|
||||
|
||||
def __str__(self):
|
||||
return f"Tg item {self.id}"
|
|
@ -0,0 +1,12 @@
|
|||
from rest_framework import serializers
|
||||
|
||||
from .models import Item
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger("root")
|
||||
|
||||
|
||||
class ItemSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Item
|
||||
fields = '__all__'
|
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -0,0 +1,60 @@
|
|||
from django.conf import settings
|
||||
from telegram import (
|
||||
ForceReply,
|
||||
Update,
|
||||
ReplyParameters,
|
||||
)
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
CommandHandler,
|
||||
MessageHandler,
|
||||
filters,
|
||||
CallbackContext,
|
||||
)
|
||||
from telegram.constants import ParseMode, ChatType
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger("root")
|
||||
|
||||
|
||||
class TgBotApp:
|
||||
_app = None
|
||||
|
||||
async def start(self, update: Update, context: CallbackContext):
|
||||
user = update.effective_user
|
||||
# logger.info(update)
|
||||
await update.message.reply_html(
|
||||
rf"Hi {user.mention_html()}!",
|
||||
# reply_markup=ForceReply(selective=True),
|
||||
reply_parameters=ReplyParameters(message_id=update.message.message_id),
|
||||
)
|
||||
|
||||
async def set_webhook(self, url):
|
||||
if not self._app:
|
||||
logger.error("no app")
|
||||
return
|
||||
app = self._app
|
||||
await app.bot.set_webhook(url, allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
async def init_tg(self):
|
||||
self._app = (
|
||||
Application.builder()
|
||||
.token(settings.TGBOT["token"])
|
||||
.concurrent_updates(True)
|
||||
.updater(None)
|
||||
.build()
|
||||
)
|
||||
self._app.add_handler(CommandHandler("start", self.start))
|
||||
self._app.add_handler(MessageHandler(filters.ChatType.PRIVATE, self.start))
|
||||
|
||||
logger.info(
|
||||
{
|
||||
"app": self._app,
|
||||
"bot": self._app.bot,
|
||||
"handlers": self._app.handlers,
|
||||
}
|
||||
)
|
||||
await self._app.initialize()
|
||||
await self._app.start()
|
||||
return self._app
|
|
@ -0,0 +1,33 @@
|
|||
import json
|
||||
|
||||
from telegram import Update
|
||||
|
||||
from asgiref.sync import async_to_sync
|
||||
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.response import Response
|
||||
|
||||
import time
|
||||
from .apps import TgBotClass
|
||||
from .models import Item
|
||||
from .serializers import ItemSerializer
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger("root")
|
||||
|
||||
|
||||
class ItemViewSet(viewsets.ViewSet):
|
||||
queryset = Item.objects.all()
|
||||
serializer_class = ItemSerializer
|
||||
|
||||
@async_to_sync
|
||||
async def create(self, request):
|
||||
req = json.loads(request.body)
|
||||
update_item = Update.de_json(data=req, bot=TgBotClass.app.bot)
|
||||
TgBotClass.my_queue.put(update_item)
|
||||
logger.info(
|
||||
f"Update from {update_item.message.chat.id} pass to que and its size is {TgBotClass.my_queue.qsize()}"
|
||||
)
|
||||
|
||||
return Response({"result": "pass data to tgbot"})
|
|
@ -0,0 +1,6 @@
|
|||
from django.contrib import admin
|
||||
from .models import CustomTable, BaseCustomField
|
||||
|
||||
admin.site.register(CustomTable)
|
||||
admin.site.register(BaseCustomField)
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class TmcConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'tmc'
|
|
@ -0,0 +1,14 @@
|
|||
from django.conf import settings
|
||||
from django.db import models
|
||||
|
||||
class BaseCustomField(models.Model):
|
||||
name = models.CharField(max_length=120, )
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class CustomTable(models.Model):
|
||||
name = models.CharField(max_length=120, )
|
||||
fields = models.ManyToManyField(BaseCustomField)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -1,3 +1,2 @@
|
|||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
|
@ -0,0 +1,12 @@
|
|||
services:
|
||||
app:
|
||||
entrypoint:
|
||||
- sleep
|
||||
- infinity
|
||||
image: docker/dev-environments-javascript:stable-1
|
||||
init: true
|
||||
volumes:
|
||||
- type: bind
|
||||
source: /var/run/docker.sock
|
||||
target: /var/run/docker.sock
|
||||
|
4
dev.sh
4
dev.sh
|
@ -1,3 +1,3 @@
|
|||
#!/bin/bash
|
||||
cd front && npm run dev &
|
||||
cd back && poetry run task server &
|
||||
x-terminal-emulator -title "To Invetory FRONT" -e "cd front && npm run dev -- --host"&
|
||||
x-terminal-emulator -title "To Invetory BACK" -e "poetry run task server"
|
|
@ -0,0 +1,55 @@
|
|||
services:
|
||||
back:
|
||||
build:
|
||||
context: ./back
|
||||
dockerfile: Dockerfile
|
||||
container_name: toinv-back
|
||||
restart: always
|
||||
expose:
|
||||
- "8000"
|
||||
# healthcheck:
|
||||
# test: curl -f http://localhost:8000/ || exit 1
|
||||
# interval: 5s
|
||||
# timeout: 3s
|
||||
volumes:
|
||||
- ./.env:/app/.env
|
||||
networks:
|
||||
- toinv-network
|
||||
image: ci.svs-tech.pro/toinv_back:latest
|
||||
|
||||
front:
|
||||
build:
|
||||
context: ./front
|
||||
dockerfile: Dockerfile
|
||||
container_name: toinv-front
|
||||
restart: always
|
||||
expose:
|
||||
- "3000"
|
||||
# depends_on:
|
||||
# back:
|
||||
# condition: service_healthy
|
||||
networks:
|
||||
- toinv-network
|
||||
image: ci.svs-tech.pro/toinv_front:latest
|
||||
|
||||
nginx:
|
||||
image: ci.svs-tech.pro/nginx:1.25
|
||||
container_name: toinv-nginx
|
||||
restart: always
|
||||
ports:
|
||||
- "80:80"
|
||||
# depends_on:
|
||||
# back:
|
||||
# condition: service_healthy
|
||||
links:
|
||||
- back:back
|
||||
- front:front
|
||||
volumes:
|
||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
|
||||
- ./nginx/conf.d:/etc/nginx/conf.d
|
||||
networks:
|
||||
- toinv-network
|
||||
|
||||
networks:
|
||||
toinv-network:
|
||||
driver: bridge
|
|
@ -0,0 +1,12 @@
|
|||
FROM ci.svs-tech.pro/library/node:21
|
||||
|
||||
RUN mkdir -p /src
|
||||
|
||||
COPY package.json src/package.json
|
||||
|
||||
WORKDIR /src
|
||||
RUN npm install --omit=dev
|
||||
|
||||
COPY . /src
|
||||
RUN npm run build
|
||||
CMD npm run preview -- --host
|
|
@ -0,0 +1,6 @@
|
|||
export default defineAppConfig({
|
||||
ui: {
|
||||
primary: 'pink',
|
||||
gray: 'cool'
|
||||
}
|
||||
})
|
|
@ -1,5 +1,20 @@
|
|||
<script setup lang="ts">
|
||||
import 'assets/main.scss'
|
||||
import Logo from 'assets/logo.svg'
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<NuxtWelcome />
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="logo">
|
||||
<Logo />
|
||||
</div>
|
||||
<NuxtLink to="/">Инвентаризация</NuxtLink>
|
||||
</div>
|
||||
<div class="sidebar">
|
||||
<Sidebar />
|
||||
</div>
|
||||
<div class="content">
|
||||
<NuxtPage />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="m15.5 17.125l4.95-4.95q.275-.275.7-.275t.7.275t.275.7t-.275.7l-5.65 5.65q-.3.3-.7.3t-.7-.3l-2.85-2.85q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275zM5 21q-.825 0-1.412-.587T3 19V5q0-.825.588-1.412T5 3h4.175q.275-.875 1.075-1.437T12 1q1 0 1.788.563T14.85 3H19q.825 0 1.413.588T21 5v4q0 .425-.288.713T20 10t-.712-.288T19 9V5h-2v2q0 .425-.288.713T16 8H8q-.425 0-.712-.288T7 7V5H5v14h5q.425 0 .713.288T11 20t-.288.713T10 21zm7-16q.425 0 .713-.288T13 4t-.288-.712T12 3t-.712.288T11 4t.288.713T12 5"/></svg>
|
After Width: | Height: | Size: 611 B |
|
@ -0,0 +1,55 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
h1 {
|
||||
@apply text-2xl;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@apply text-xl;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@apply text-lg;
|
||||
}
|
||||
|
||||
a[href]:not([class*=text]) {
|
||||
@apply text-primary-500 hover:text-primary-600
|
||||
}
|
||||
|
||||
.container {
|
||||
@apply grid grid-cols-12 mx-auto gap-4
|
||||
}
|
||||
|
||||
.header {
|
||||
@apply col-span-12 flex gap-2 p-2.5;
|
||||
|
||||
.logo {
|
||||
@apply text-primary text-2xl
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
@apply col-span-2
|
||||
}
|
||||
|
||||
.content {
|
||||
@apply col-span-10
|
||||
}
|
||||
|
||||
dl {
|
||||
@apply grid grid-cols-12;
|
||||
dt {
|
||||
@apply col-span-full
|
||||
}
|
||||
dd {
|
||||
@apply col-span-full col-start-2;
|
||||
&:last-of-type {
|
||||
@apply mb-2
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
<script setup lang="ts">
|
||||
import { apiBase } from '~/helpers';
|
||||
import type { ApiTypeList, ApiTypeExternal, ApiElementSave } from '~/helpers';
|
||||
import type { FormError, FormSubmitEvent } from '#ui/types'
|
||||
|
||||
const props = defineProps(['elements', 'partner'])
|
||||
const route = useRoute()
|
||||
|
||||
const headers = new Headers();
|
||||
headers.append("Content-Type", "application/json");
|
||||
|
||||
type ExternalDataType = {
|
||||
partner?: ApiTypeExternal[],
|
||||
categories?: ApiTypeExternal[][],
|
||||
element?: ApiTypeExternal[],
|
||||
}
|
||||
type StateDataType = {
|
||||
partner?: string
|
||||
categories?: string[]
|
||||
inventory?: string
|
||||
element?: string
|
||||
element_id?: string
|
||||
element_additional_data?: string
|
||||
}
|
||||
const loading = ref(false)
|
||||
const state = reactive<StateDataType>({
|
||||
partner: undefined,
|
||||
categories: [],
|
||||
inventory: route.params.inv_id as string || undefined,
|
||||
element: undefined,
|
||||
element_id: undefined,
|
||||
element_additional_data: undefined
|
||||
})
|
||||
const external_data = reactive<ExternalDataType>({
|
||||
partner: [],
|
||||
categories: [],
|
||||
element: [],
|
||||
})
|
||||
const show_error = ref()
|
||||
|
||||
const elements = ref(props.elements)
|
||||
const validate = (state: any): FormError[] => {
|
||||
const errors = []
|
||||
const txt = 'Это поле обязательно'
|
||||
if (!state.partner) errors.push({ path: 'partner', message: txt })
|
||||
if (!external_data || !external_data.partner || !external_data.partner.find(el => el.Ref_Key == state.partner)) {
|
||||
errors.push({ path: 'partner', message: txt })
|
||||
}
|
||||
if (!state.element_id) errors.push({ path: 'element_id', message: txt })
|
||||
// if (!state.element_additional_data) errors.push({ path: 'element_additional_data', message: txt })
|
||||
return errors
|
||||
}
|
||||
|
||||
async function onSubmit(event: FormSubmitEvent<any>) {
|
||||
show_error.value = undefined
|
||||
const prepader_data = event.data
|
||||
if (!external_data || !external_data.partner) {
|
||||
return false
|
||||
}
|
||||
prepader_data.partner_name = external_data.partner.find(el => el.Ref_Key == state.partner)?.Description
|
||||
|
||||
const data = await $fetch<ApiElementSave>(`${apiBase}/element/`, {
|
||||
method: 'POST', body: JSON.stringify(prepader_data), onResponseError: (error) => {
|
||||
if (error.response.status == 500) {
|
||||
show_error.value = Object.entries(error.response._data).map(el => `${el[0]}: ${el[1]}`).join('\n')
|
||||
}
|
||||
}
|
||||
})
|
||||
const inv_id = route.params.inv_id || data.inventory?.id
|
||||
if (!route.params.inv_id) {
|
||||
navigateTo(`/organization/p_${data.partner.id}/i_${data.inventory.id}`)
|
||||
} else {
|
||||
const newElements = await $fetch<ApiTypeList>(`${apiBase}/element?inventory_id=${inv_id}`, { headers })
|
||||
elements.value = newElements.results
|
||||
external_data.element = []
|
||||
external_data.categories = []
|
||||
state.categories = []
|
||||
state.element = undefined
|
||||
state.element_id = undefined
|
||||
state.element_additional_data = undefined
|
||||
}
|
||||
}
|
||||
|
||||
const searchInExternal = (q: string) => {
|
||||
if (!q.length) {
|
||||
return external_data.partner?.splice(0, 10)
|
||||
}
|
||||
return external_data.partner?.filter(el => {
|
||||
return el.Description.toLowerCase().indexOf(q.toLowerCase()) !== -1
|
||||
}).slice(0, 10)
|
||||
}
|
||||
|
||||
const loadPartners = async () => {
|
||||
loading.value = true
|
||||
const data = await $fetch<ApiTypeExternal[]>(`${apiBase}/partner/external/`)
|
||||
if (data) {
|
||||
external_data.partner = data
|
||||
if (props.partner) {
|
||||
state.partner = props.partner
|
||||
}
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
const loadCategories = async () => {
|
||||
loading.value = true
|
||||
|
||||
const lastCat = state.categories?.at(-1) || ''
|
||||
const data = await $fetch<ApiTypeExternal[]>(`${apiBase}/element/external_categories/${lastCat}`)
|
||||
if (data.length) {
|
||||
external_data.categories?.push(data)
|
||||
} else {
|
||||
await loadElements()
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
const loadElements = async () => {
|
||||
loading.value = true
|
||||
|
||||
const lastCat = state.categories?.at(-1) || ''
|
||||
const data = await $fetch<ApiTypeExternal[]>(`${apiBase}/element/external/${lastCat}`)
|
||||
if (data) {
|
||||
external_data.element = data
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
const loadDeepCategories = async (i: number) => {
|
||||
if ((i + 1) <= (state.categories as string[]).length) {
|
||||
state.categories = state.categories?.slice(0, i + 1)
|
||||
external_data.categories = external_data.categories?.slice(0, i + 1)
|
||||
|
||||
state.element = undefined
|
||||
external_data.element = []
|
||||
}
|
||||
|
||||
loadCategories()
|
||||
}
|
||||
onMounted(async () => {
|
||||
await loadPartners()
|
||||
await loadCategories()
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div class="grid grid-cols-10 gap-4">
|
||||
<div class="col-span-7">
|
||||
<UForm :state="state" :validate="validate" class="flex flex-col gap-4" @submit="onSubmit">
|
||||
<UFormGroup label="Выбрать организацию" name="partner">
|
||||
<USelectMenu v-model="state.partner" :options="external_data.partner" value-attribute="Ref_Key"
|
||||
option-attribute="Description" :searchable="searchInExternal"
|
||||
searchable-placeholder="Выберите организацию из списка контрагентов" :loading="loading"
|
||||
:disabled="!!props.partner" />
|
||||
</UFormGroup>
|
||||
<UFormGroup label="Добавить элемент инвентаризации" v-if="state.partner" :help="!external_data.element?.length ? `Последовательно
|
||||
выбирайте категорию. Если все выбрали, а элементов нет -
|
||||
значит в этой категории нет элементов`: ''">
|
||||
<template v-for="(item, i) in external_data.categories">
|
||||
<USelectMenu v-model="(state.categories as string[])[i]" :options="item"
|
||||
value-attribute="Ref_Key" option-attribute="Description" :searchable="true"
|
||||
:loading="loading" :placeholder="`Категории (${item.length})`"
|
||||
@change="loadDeepCategories(i)" />
|
||||
</template>
|
||||
<USelectMenu v-if="external_data.element?.length" v-model="state.element"
|
||||
:options="external_data.element" value-attribute="Ref_Key" option-attribute="Description"
|
||||
:searchable="true" :loading="loading"
|
||||
:placeholder="`Элементы (${external_data.element.length})`" />
|
||||
</UFormGroup>
|
||||
<div v-if="state.element">
|
||||
<h4>Данные об элементе «{{ external_data.element?.find(el => el['Ref_Key'] ===
|
||||
state.element)?.Description }}»</h4>
|
||||
<UFormGroup label="ID" name="element_id">
|
||||
<UInput placeholder="ID" v-model="state.element_id" />
|
||||
</UFormGroup>
|
||||
<UFormGroup label="Дополнительные сведения" name="element_additional_data">
|
||||
<UTextarea placeholder="Дополнительные сведения" v-model="state.element_additional_data" />
|
||||
</UFormGroup>
|
||||
</div>
|
||||
|
||||
<UButton type="submit" :disabled="!state.element_id">
|
||||
Сохранить
|
||||
</UButton>
|
||||
</UForm>
|
||||
</div>
|
||||
<div class="col-span-3 flex flex-col gap-4">
|
||||
<h2>{{ external_data.partner?.find(el => el["Ref_Key"] == state.partner)?.Description }}</h2>
|
||||
<UAlert v-if="show_error" title="Server error" :description="show_error" color="primary" />
|
||||
<dl v-if="elements?.length">
|
||||
<template v-for="item in elements">
|
||||
<dt>
|
||||
<Element :id="item.external_id" />
|
||||
</dt>
|
||||
<dd>{{ item.element_id }}</dd>
|
||||
<dd>{{ item.additional_text }}</dd>
|
||||
</template>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
label {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,32 @@
|
|||
<script setup lang="ts">
|
||||
import { apiBase } from '~/helpers';
|
||||
import type { ApiTypeExternal } from '~/helpers';
|
||||
|
||||
type ExternalNameType = { [s: string]: string; }
|
||||
|
||||
const props = defineProps(['id'])
|
||||
const id = props.id
|
||||
const external_elements = useState<ExternalNameType>('external_elements', () => { return {} })
|
||||
const name = ref()
|
||||
|
||||
const loadOneElement = async (id: string) => {
|
||||
external_elements.value[id] = 'loading'
|
||||
const data = await $fetch<ApiTypeExternal>(`${apiBase}/element/external/id/${id}`)
|
||||
external_elements.value[id] = data.Description
|
||||
name.value = external_elements.value[id]
|
||||
}
|
||||
|
||||
if (external_elements.value[id]) {
|
||||
name.value = external_elements.value[id]
|
||||
} else {
|
||||
await loadOneElement(id)
|
||||
}
|
||||
watch(external_elements, () => {
|
||||
if (name.value !== external_elements.value[id]) {
|
||||
name.value = external_elements.value[id]
|
||||
}
|
||||
}, { deep: true })
|
||||
</script>
|
||||
<template>
|
||||
{{ name }}
|
||||
</template>
|
|
@ -0,0 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
const route = useRoute()
|
||||
|
||||
const links = [
|
||||
{
|
||||
label: 'Организации',
|
||||
icon: 'i-heroicons-archive-box',
|
||||
to: '/organization'
|
||||
}
|
||||
]
|
||||
</script>
|
||||
<template>
|
||||
<UVerticalNavigation :links="links" />
|
||||
</template>
|
|
@ -0,0 +1,35 @@
|
|||
const config = useRuntimeConfig()
|
||||
export const apiBase = config.public.apiBase
|
||||
|
||||
export type ApiTypeList = {
|
||||
count: number;
|
||||
next?: any;
|
||||
previous?: any;
|
||||
results: ApiTypeBase[]
|
||||
}
|
||||
export type ApiTypeBase =
|
||||
ApiPartner | ApiInventory | ApiElement;
|
||||
|
||||
|
||||
export type ApiPartner = { id: number, external_id: number, name: string, total_inventory: number }
|
||||
export type ApiInventory = { id: number, partner: number, name: string }
|
||||
export type ApiElement = { id: number, external_id: string, element_id: number, photo: string, additional_text: string, inventory: number }
|
||||
export type ApiElementSave = {
|
||||
partner: ApiPartner,
|
||||
inventory: ApiInventory,
|
||||
element: ApiElement
|
||||
}
|
||||
export type ApiTypeExternal = {
|
||||
'НаименованиеПолное': string;
|
||||
Description: string;
|
||||
Ref_Key: string;
|
||||
}
|
||||
|
||||
export const makeColumns = (cols: string[]) => {
|
||||
return cols.map(el => {
|
||||
return {
|
||||
key: el,
|
||||
label: el.toUpperCase()
|
||||
}
|
||||
})
|
||||
}
|
|
@ -1,4 +1,11 @@
|
|||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
devtools: { enabled: true }
|
||||
ssr: false,
|
||||
devtools: { enabled: true },
|
||||
modules: ["@nuxt/ui", "nuxt-svgo"],
|
||||
runtimeConfig: {
|
||||
public: {
|
||||
apiBase: '/api',
|
||||
},
|
||||
},
|
||||
})
|
File diff suppressed because it is too large
Load Diff
|
@ -10,8 +10,14 @@
|
|||
"postinstall": "nuxt prepare"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxt/ui": "^2.16.0",
|
||||
"nuxt": "^3.11.2",
|
||||
"nuxt-svgo": "^4.0.1",
|
||||
"vue": "^3.4.27",
|
||||
"vue-router": "^4.3.2"
|
||||
"vue-router": "^4.3.2",
|
||||
"yup": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"sass": "^1.77.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
pages index vue
|
||||
</template>
|
|
@ -0,0 +1,21 @@
|
|||
<script setup lang="ts">
|
||||
import { apiBase, makeColumns } from '~/helpers';
|
||||
import type { ApiTypeList } from '~/helpers';
|
||||
|
||||
const headers = new Headers();
|
||||
headers.append("Content-Type", "application/json");
|
||||
|
||||
const { data } = await useFetch<ApiTypeList>(`${apiBase}/partner/`, { headers })
|
||||
</script>
|
||||
<template>
|
||||
<div class="mb-4">
|
||||
<UButton icon="i-heroicons-plus" to="/organization/new">Новая инвентаризация</UButton>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<UTable :rows="data?.results" :columns="makeColumns(['id', 'name', 'external_id', 'total_inventory'])">
|
||||
<template #name-data="{ row }">
|
||||
<NuxtLink :to="`/organization/p_${row.id}`">{{ row.name }}</NuxtLink>
|
||||
</template>
|
||||
</UTable>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<Edit />
|
||||
</template>
|
|
@ -0,0 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import { apiBase } from '~/helpers';
|
||||
import type { ApiPartner, ApiTypeList } from '~/helpers';
|
||||
|
||||
const headers = new Headers();
|
||||
headers.append("Content-Type", "application/json");
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const { data: partner } = await useFetch<ApiPartner>(`${apiBase}/partner/${route.params.org_id}`, { headers })
|
||||
const { data: elements } = await useFetch<ApiTypeList>(`${apiBase}/element?inventory_id=${route.params.inv_id}`, { headers })
|
||||
</script>
|
||||
<template>
|
||||
<Edit :elements="elements?.results" :inventory="route.params.org_id" :partner="partner?.external_id"/>
|
||||
</template>
|
|
@ -0,0 +1,42 @@
|
|||
<script setup lang="ts">
|
||||
import { apiBase, makeColumns } from '~/helpers';
|
||||
import type { ApiTypeList } from '~/helpers';
|
||||
|
||||
const headers = new Headers();
|
||||
headers.append("Content-Type", "application/json");
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const inventory = ref()
|
||||
const elements = ref()
|
||||
onMounted(async () => {
|
||||
const inventory_data = await $fetch<ApiTypeList>(`${apiBase}/inventory/${route.params.inv_id}`, { headers })
|
||||
inventory.value = inventory_data
|
||||
|
||||
const elements_data = await $fetch<ApiTypeList>(`${apiBase}/element?inventory_id=${route.params.inv_id}`, { headers })
|
||||
elements.value = elements_data
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<UCard class="mb-4" v-if="inventory">
|
||||
<template #header>
|
||||
Инвентаризация <strong>{{ inventory.name }}</strong>
|
||||
</template>
|
||||
<ul class="flex flex-col gap-2">
|
||||
<li>Всего элементов: {{ inventory.total_elements }}</li>
|
||||
</ul>
|
||||
<template #footer>
|
||||
<UButton icon="i-heroicons-plus"
|
||||
:to="`/organization/p_${route.params.org_id}/i_${route.params.inv_id}/edit`">
|
||||
Добавить элемент</UButton>
|
||||
</template>
|
||||
</UCard>
|
||||
<div class="mb-4">
|
||||
<UTable :rows="elements?.results"
|
||||
:columns="makeColumns(['id', 'external_id', 'element_id', 'photo', 'additional_text'])">
|
||||
<template #external_id-data="{ row }">
|
||||
<Element :id="row.external_id" />
|
||||
</template>
|
||||
</UTable>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,57 @@
|
|||
<script setup lang="ts">
|
||||
import { apiBase, makeColumns } from '~/helpers';
|
||||
import type { ApiPartner, ApiTypeList } from '~/helpers';
|
||||
|
||||
const headers = new Headers();
|
||||
headers.append("Content-Type", "application/json");
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const partner = ref()
|
||||
const partnerRemote = ref()
|
||||
const inventory = ref()
|
||||
onMounted(async () => {
|
||||
const partner_data = await $fetch<ApiPartner>(`${apiBase}/partner/${route.params.org_id}`, { headers })
|
||||
partner.value = partner_data
|
||||
|
||||
const partnerRemote_data = await $fetch<ApiPartner>(`${apiBase}/partner/external/${partner_data.external_id}`, { headers })
|
||||
partnerRemote.value = partnerRemote_data
|
||||
|
||||
const inventory_data = await $fetch<ApiTypeList>(`${apiBase}/inventory?partner_id=${route.params.org_id}`, { headers })
|
||||
inventory.value = inventory_data
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<UCard class="mb-4" v-if="partner">
|
||||
<template #header>
|
||||
Контрагент <strong>{{ partner.name }}</strong>
|
||||
</template>
|
||||
<ul class="flex flex-col gap-2">
|
||||
<li>Всего инвентаризаций: {{ partner.total_inventory }}</li>
|
||||
<li>1C ID: {{ partner.external_id }}
|
||||
<ul class="p-4">
|
||||
<template v-for="(value, name) in partnerRemote">
|
||||
<li>{{ name }}: {{ value }}</li>
|
||||
</template>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<template #footer>
|
||||
<UButton icon="i-heroicons-plus"
|
||||
:to="`/organization/p_${route.params.org_id}/new`">
|
||||
Новая инвентаризацию</UButton>
|
||||
</template>
|
||||
</UCard>
|
||||
<div class="mb-4">
|
||||
<UTable :rows="inventory?.results" :columns="makeColumns(['id', 'name', 'created_at', 'total_elements',])">
|
||||
<template #name-data="{ row }">
|
||||
<NuxtLink :to="`/organization/p_${route.params.org_id}/i_${row.id}`">
|
||||
{{ row.name }}
|
||||
</NuxtLink>
|
||||
</template>
|
||||
<template #created_at-data="{ row }">
|
||||
{{ new Date(row.created_at).toLocaleString('ru-RU') }}
|
||||
</template>
|
||||
</UTable>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import { apiBase, } from '~/helpers';
|
||||
import type { ApiPartner } from '~/helpers';
|
||||
|
||||
const headers = new Headers();
|
||||
headers.append("Content-Type", "application/json");
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
onMounted(async () => {
|
||||
const partner_data = await $fetch<ApiPartner>(`${apiBase}/partner/${route.params.org_id}`, { headers })
|
||||
const prepader_data = {
|
||||
partner: partner_data.external_id,
|
||||
partner_name: partner_data.name,
|
||||
}
|
||||
const data = await $fetch(`${apiBase}/inventory/`, { method: 'POST', body: JSON.stringify(prepader_data) })
|
||||
navigateTo(`/organization/p_${data.partner.id}/i_${data.inventory.id}/edit`)
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
Создается инвентаризация..
|
||||
</template>
|
|
@ -0,0 +1,62 @@
|
|||
user root;
|
||||
worker_processes auto;
|
||||
error_log /var/log/nginx/error.log;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
upstream django {
|
||||
server back:8000;
|
||||
keepalive 16;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
proxy_pass http://front:3000;
|
||||
proxy_set_header Host $host:$server_port;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
location /api/ {
|
||||
proxy_pass http://back:8000/api/;
|
||||
}
|
||||
|
||||
location /admin/ {
|
||||
proxy_pass http://back:8000/admin/;
|
||||
}
|
||||
location /static/admin/ {
|
||||
proxy_pass http://back:8000/static/admin/;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "to_inventory",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
Loading…
Reference in New Issue