Compare commits
10 Commits
f24a2760a9
...
f293cc7018
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f293cc7018 | ||
|
|
445ae78095 | ||
|
|
b924442631 | ||
|
|
479d8b8faa | ||
|
|
07d7e8604f | ||
|
|
ae8a14b83c | ||
|
|
78746e6071 | ||
|
|
824ad25a17 | ||
|
|
e26ab5eea6 | ||
|
|
eb010cb6de |
@@ -12,7 +12,7 @@ class DistributedProductListSerializer(serializers.ModelSerializer):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = DistributedProduct
|
model = DistributedProduct
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'product', 'quantity', 'employee_name', 'quantity', 'user', 'created_at'
|
'id', 'product', 'quantity', 'employee_name', 'quantity', 'user', 'created_at', 'date'
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_user(self, obj):
|
def get_user(self, obj):
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ class DistrictCreateSerializer(serializers.Serializer):
|
|||||||
if not user:
|
if not user:
|
||||||
raise serializers.ValidationError({"user_id": "Foydalanuvchi topilmadi"})
|
raise serializers.ValidationError({"user_id": "Foydalanuvchi topilmadi"})
|
||||||
data['user'] = user
|
data['user'] = user
|
||||||
|
if District.objects.filter(name=data['name'], user=user).exists():
|
||||||
|
raise serializers.ValidationError({'name': "District qo'shib bolmadi"})
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
|
|||||||
7
core/apps/dashboard/serializers/send_message.py
Normal file
7
core/apps/dashboard/serializers/send_message.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# rest framework
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
|
||||||
|
class SendMessageSerializer(serializers.Serializer):
|
||||||
|
user_ids = serializers.ListField(child=serializers.IntegerField())
|
||||||
|
message = serializers.CharField()
|
||||||
@@ -19,7 +19,7 @@ class SupportListSerializer(serializers.ModelSerializer):
|
|||||||
return {
|
return {
|
||||||
'id': obj.district.id,
|
'id': obj.district.id,
|
||||||
'name': obj.district.name,
|
'name': obj.district.name,
|
||||||
}
|
} if obj.district else None
|
||||||
|
|
||||||
def get_user(self, obj):
|
def get_user(self, obj):
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ from core.apps.dashboard.views.location import LocationViewSet, UserLocationView
|
|||||||
from core.apps.dashboard.views.support import SupportListApiView
|
from core.apps.dashboard.views.support import SupportListApiView
|
||||||
# distibuted products
|
# distibuted products
|
||||||
from core.apps.dashboard.views.dis_prod import DistributedProductListApiView
|
from core.apps.dashboard.views.dis_prod import DistributedProductListApiView
|
||||||
|
# send message
|
||||||
|
from core.apps.dashboard.views.send_message import SendMessageToEmployee
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
@@ -82,7 +84,10 @@ urlpatterns = [
|
|||||||
[
|
[
|
||||||
path('list/', DistributedProductListApiView.as_view(), name='distributed-product-list-api'),
|
path('list/', DistributedProductListApiView.as_view(), name='distributed-product-list-api'),
|
||||||
]
|
]
|
||||||
))
|
)),
|
||||||
|
|
||||||
|
# -------------- send message --------------
|
||||||
|
path('send_message/', SendMessageToEmployee.as_view()),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,13 @@ class DoctorViewSet(viewsets.GenericViewSet, ResponseMixin):
|
|||||||
required=False,
|
required=False,
|
||||||
type=openapi.TYPE_STRING,
|
type=openapi.TYPE_STRING,
|
||||||
),
|
),
|
||||||
|
openapi.Parameter(
|
||||||
|
in_=openapi.IN_QUERY,
|
||||||
|
type=openapi.TYPE_INTEGER,
|
||||||
|
name='user_id',
|
||||||
|
description="user id bo'yicha filter",
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
],
|
],
|
||||||
operation_description="Shifokorlar ro'yxatini olish",
|
operation_description="Shifokorlar ro'yxatini olish",
|
||||||
operation_summary="Shifokolar ro'yxati",
|
operation_summary="Shifokolar ro'yxati",
|
||||||
@@ -147,6 +154,8 @@ class DoctorViewSet(viewsets.GenericViewSet, ResponseMixin):
|
|||||||
work_place = request.query_params.get('work_place', None)
|
work_place = request.query_params.get('work_place', None)
|
||||||
sphere = request.query_params.get('sphere', None)
|
sphere = request.query_params.get('sphere', None)
|
||||||
user_full_name = request.query_params.get('user', None)
|
user_full_name = request.query_params.get('user', None)
|
||||||
|
user_id = request.query_params.get('user_id', None)
|
||||||
|
|
||||||
|
|
||||||
queryset = self.queryset.all()
|
queryset = self.queryset.all()
|
||||||
|
|
||||||
@@ -177,6 +186,8 @@ class DoctorViewSet(viewsets.GenericViewSet, ResponseMixin):
|
|||||||
Q(user__first_name__istartswith=user_full_name) |
|
Q(user__first_name__istartswith=user_full_name) |
|
||||||
Q(user__last_name__istartswith=user_full_name)
|
Q(user__last_name__istartswith=user_full_name)
|
||||||
)
|
)
|
||||||
|
if not user_id is None:
|
||||||
|
queryset = queryset.filter(user__id=user_id)
|
||||||
|
|
||||||
page = self.paginate_queryset(queryset)
|
page = self.paginate_queryset(queryset)
|
||||||
if page is not None:
|
if page is not None:
|
||||||
|
|||||||
@@ -60,6 +60,13 @@ class PharmacyViewSet(viewsets.GenericViewSet, ResponseMixin):
|
|||||||
required=False,
|
required=False,
|
||||||
type=openapi.TYPE_STRING,
|
type=openapi.TYPE_STRING,
|
||||||
),
|
),
|
||||||
|
openapi.Parameter(
|
||||||
|
in_=openapi.IN_QUERY,
|
||||||
|
type=openapi.TYPE_INTEGER,
|
||||||
|
name='user_id',
|
||||||
|
description="user id bo'yicha filter",
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@action(detail=False, methods=['get'], url_path="list")
|
@action(detail=False, methods=['get'], url_path="list")
|
||||||
@@ -70,6 +77,7 @@ class PharmacyViewSet(viewsets.GenericViewSet, ResponseMixin):
|
|||||||
place_name = request.query_params.get('place', None)
|
place_name = request.query_params.get('place', None)
|
||||||
district_name = request.query_params.get('district', None)
|
district_name = request.query_params.get('district', None)
|
||||||
user_full_name = request.query_params.get('user', None)
|
user_full_name = request.query_params.get('user', None)
|
||||||
|
user_id = request.query_params.get('user_id', None)
|
||||||
|
|
||||||
queryset = self.queryset.all()
|
queryset = self.queryset.all()
|
||||||
|
|
||||||
@@ -88,6 +96,9 @@ class PharmacyViewSet(viewsets.GenericViewSet, ResponseMixin):
|
|||||||
Q(user__first_name__istartswith=user_full_name) |
|
Q(user__first_name__istartswith=user_full_name) |
|
||||||
Q(user__last_name__istartswith=user_full_name)
|
Q(user__last_name__istartswith=user_full_name)
|
||||||
)
|
)
|
||||||
|
if not user_id is None:
|
||||||
|
queryset = queryset.filter(user__id=user_id)
|
||||||
|
|
||||||
|
|
||||||
page = self.paginate_queryset(queryset)
|
page = self.paginate_queryset(queryset)
|
||||||
if page is not None:
|
if page is not None:
|
||||||
|
|||||||
@@ -53,6 +53,13 @@ class PlaceViewSet(viewsets.GenericViewSet, ResponseMixin):
|
|||||||
required=False,
|
required=False,
|
||||||
type=openapi.TYPE_STRING,
|
type=openapi.TYPE_STRING,
|
||||||
),
|
),
|
||||||
|
openapi.Parameter(
|
||||||
|
in_=openapi.IN_QUERY,
|
||||||
|
type=openapi.TYPE_INTEGER,
|
||||||
|
name='user_id',
|
||||||
|
description="user id bo'yicha filter",
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@action(detail=False, methods=['get'], url_path="list")
|
@action(detail=False, methods=['get'], url_path="list")
|
||||||
@@ -62,6 +69,7 @@ class PlaceViewSet(viewsets.GenericViewSet, ResponseMixin):
|
|||||||
name = request.query_params.get('name', None)
|
name = request.query_params.get('name', None)
|
||||||
district_name = request.query_params.get('district', None)
|
district_name = request.query_params.get('district', None)
|
||||||
user_full_name = request.query_params.get('user', None)
|
user_full_name = request.query_params.get('user', None)
|
||||||
|
user_id = request.query_params.get('user_id', None)
|
||||||
|
|
||||||
queryset = self.queryset.all()
|
queryset = self.queryset.all()
|
||||||
|
|
||||||
@@ -77,6 +85,9 @@ class PlaceViewSet(viewsets.GenericViewSet, ResponseMixin):
|
|||||||
Q(user__first_name__istartswith=user_full_name) |
|
Q(user__first_name__istartswith=user_full_name) |
|
||||||
Q(user__last_name__istartswith=user_full_name)
|
Q(user__last_name__istartswith=user_full_name)
|
||||||
)
|
)
|
||||||
|
if not user_id is None:
|
||||||
|
queryset = queryset.filter(user__id=user_id)
|
||||||
|
|
||||||
|
|
||||||
page = self.paginate_queryset(queryset)
|
page = self.paginate_queryset(queryset)
|
||||||
if page is not None:
|
if page is not None:
|
||||||
|
|||||||
38
core/apps/dashboard/views/send_message.py
Normal file
38
core/apps/dashboard/views/send_message.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# rest framework
|
||||||
|
from rest_framework import generics, permissions
|
||||||
|
|
||||||
|
|
||||||
|
# services
|
||||||
|
from core.services.send_telegram_msg import send_message
|
||||||
|
# accounts
|
||||||
|
from core.apps.accounts.models import User
|
||||||
|
#shared
|
||||||
|
from core.apps.shared.utils.response_mixin import ResponseMixin
|
||||||
|
# dashboard
|
||||||
|
from core.apps.dashboard.serializers.send_message import SendMessageSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class SendMessageToEmployee(generics.GenericAPIView, ResponseMixin):
|
||||||
|
serializer_class = SendMessageSerializer
|
||||||
|
permission_classes = [permissions.IsAdminUser]
|
||||||
|
queryset = User.objects.all()
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
try:
|
||||||
|
serializer = self.serializer_class(data=request.data)
|
||||||
|
if serializer.is_valid():
|
||||||
|
data = serializer.validated_data
|
||||||
|
message = data.get('message')
|
||||||
|
user_ids = data.get('user_ids')
|
||||||
|
users = User.objects.filter(id__in=user_ids)
|
||||||
|
for user in users:
|
||||||
|
send_message(chat_id=user.telegram_id, message=message)
|
||||||
|
return self.success_response(
|
||||||
|
data={},
|
||||||
|
message="Xabar yuborildi"
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
return self.error_response(
|
||||||
|
data=str(e),
|
||||||
|
message="xatolik, backend dasturchi bilan boglaning"
|
||||||
|
)
|
||||||
@@ -19,6 +19,7 @@ urlpatterns = [
|
|||||||
path('list/', order_view.OrderListApiView.as_view(), name='order-list-api'),
|
path('list/', order_view.OrderListApiView.as_view(), name='order-list-api'),
|
||||||
path('create/', order_view.OrderCreateApiView.as_view(), name='order-create-api'),
|
path('create/', order_view.OrderCreateApiView.as_view(), name='order-create-api'),
|
||||||
path('<int:id>/update/', order_view.OrderUpdateApiView.as_view(), name='order-update-api'),
|
path('<int:id>/update/', order_view.OrderUpdateApiView.as_view(), name='order-update-api'),
|
||||||
|
path('<int:id>/send_pdf/', order_view.SendFileToTelegramApiView.as_view(), name='order-send-pdf-api'),
|
||||||
]
|
]
|
||||||
)),
|
)),
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
|
|
||||||
# rest framework
|
# rest framework
|
||||||
from rest_framework import generics, permissions
|
from rest_framework import generics, permissions, views
|
||||||
|
|
||||||
# drf yasg
|
# drf yasg
|
||||||
from drf_yasg.utils import swagger_auto_schema
|
from drf_yasg.utils import swagger_auto_schema
|
||||||
@@ -14,6 +14,9 @@ from core.apps.orders.serializers.order import OrderCreateSerializer, OrderListS
|
|||||||
from core.apps.shared.utils.response_mixin import ResponseMixin
|
from core.apps.shared.utils.response_mixin import ResponseMixin
|
||||||
from core.apps.shared.serializers.base import BaseResponseSerializer, SuccessResponseSerializer
|
from core.apps.shared.serializers.base import BaseResponseSerializer, SuccessResponseSerializer
|
||||||
|
|
||||||
|
# services
|
||||||
|
from core.services.send_telegram_msg import send_to_telegram
|
||||||
|
|
||||||
|
|
||||||
class OrderCreateApiView(generics.GenericAPIView, ResponseMixin):
|
class OrderCreateApiView(generics.GenericAPIView, ResponseMixin):
|
||||||
serializer_class = OrderCreateSerializer
|
serializer_class = OrderCreateSerializer
|
||||||
@@ -94,3 +97,27 @@ class OrderUpdateApiView(generics.GenericAPIView, ResponseMixin):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return self.error_response(data=str(e), message='xatolik')
|
return self.error_response(data=str(e), message='xatolik')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SendFileToTelegramApiView(views.APIView, ResponseMixin):
|
||||||
|
permission_classes = [permissions.IsAuthenticated]
|
||||||
|
|
||||||
|
def get(self, request, id):
|
||||||
|
try:
|
||||||
|
order = Order.objects.filter(id=id).first()
|
||||||
|
if not order:
|
||||||
|
return self.failure_response(
|
||||||
|
data={},
|
||||||
|
message="Order not found"
|
||||||
|
)
|
||||||
|
send_to_telegram(request.user.telegram_id, order.id)
|
||||||
|
return self.success_response(
|
||||||
|
data={},
|
||||||
|
message='Succefully send!'
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
return self.error_response(
|
||||||
|
data=str(e),
|
||||||
|
message="xatolik, backend dasturchiga murojaat qiling"
|
||||||
|
)
|
||||||
|
|||||||
19
core/apps/shared/migrations/0017_alter_support_district.py
Normal file
19
core/apps/shared/migrations/0017_alter_support_district.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 5.2 on 2025-12-04 12:35
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('shared', '0016_plan_comment_plan_doctor_plan_extra_location_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='support',
|
||||||
|
name='district',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='supports', to='shared.district'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 5.2 on 2025-12-11 13:15
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('shared', '0017_alter_support_district'),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='district',
|
||||||
|
unique_together={('user', 'name')},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -14,3 +14,6 @@ class District(BaseModel):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
unique_together = ('user', 'name')
|
||||||
@@ -13,7 +13,13 @@ class Support(BaseModel):
|
|||||||
('HELP', 'yordam'),
|
('HELP', 'yordam'),
|
||||||
)
|
)
|
||||||
|
|
||||||
district = models.ForeignKey(District, on_delete=models.CASCADE, related_name='supports')
|
district = models.ForeignKey(
|
||||||
|
District,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
related_name='supports',
|
||||||
|
blank=True,
|
||||||
|
null=True
|
||||||
|
)
|
||||||
problem = models.TextField()
|
problem = models.TextField()
|
||||||
date = models.DateField()
|
date = models.DateField()
|
||||||
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='supports')
|
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='supports')
|
||||||
|
|||||||
24
core/apps/shared/serializers/dis_product.py
Normal file
24
core/apps/shared/serializers/dis_product.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# rest framework
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
# orders
|
||||||
|
from core.apps.orders.models import DistributedProduct
|
||||||
|
|
||||||
|
|
||||||
|
class DistributedProductListSerializer(serializers.ModelSerializer):
|
||||||
|
product = serializers.SerializerMethodField(method_name='get_product')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = DistributedProduct
|
||||||
|
fields = [
|
||||||
|
'id', 'product', 'quantity', 'employee_name', 'quantity', 'created_at', 'date'
|
||||||
|
]
|
||||||
|
ref_name = "DisProductListSerializer"
|
||||||
|
|
||||||
|
def get_product(self, obj):
|
||||||
|
return {
|
||||||
|
"id": obj.product.id,
|
||||||
|
"name": obj.product.name,
|
||||||
|
"price": obj.product.price,
|
||||||
|
}
|
||||||
|
|
||||||
@@ -9,16 +9,17 @@ from core.apps.shared.models import Support, District
|
|||||||
|
|
||||||
|
|
||||||
class SupportCreateSerializer(serializers.Serializer):
|
class SupportCreateSerializer(serializers.Serializer):
|
||||||
district_id = serializers.IntegerField()
|
district_id = serializers.IntegerField(required=False)
|
||||||
problem = serializers.CharField()
|
problem = serializers.CharField()
|
||||||
date = serializers.DateField()
|
date = serializers.DateField()
|
||||||
type = serializers.ChoiceField(choices=Support.TYPE)
|
type = serializers.ChoiceField(choices=Support.TYPE)
|
||||||
|
|
||||||
def validate(self, data):
|
def validate(self, data):
|
||||||
district = District.objects.filter(id=data['district_id']).first()
|
if data.get('district_id'):
|
||||||
if not district:
|
district = District.objects.filter(id=data['district_id']).first()
|
||||||
raise serializers.ValidationError({'district': "district not found"})
|
if not district:
|
||||||
data['district'] = district
|
raise serializers.ValidationError({'district': "district not found"})
|
||||||
|
data['district'] = district
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
@@ -30,3 +31,21 @@ class SupportCreateSerializer(serializers.Serializer):
|
|||||||
type=validated_data.get('type'),
|
type=validated_data.get('type'),
|
||||||
problem=validated_data.get('problem' )
|
problem=validated_data.get('problem' )
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SupportListSerializer(serializers.ModelSerializer):
|
||||||
|
district = serializers.SerializerMethodField(method_name='get_district')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Support
|
||||||
|
fields = [
|
||||||
|
'id', 'problem', 'date', 'type', 'district', 'created_at'
|
||||||
|
]
|
||||||
|
ref_name = "SupportListSerializerForUser"
|
||||||
|
|
||||||
|
def get_district(self, obj):
|
||||||
|
return {
|
||||||
|
'id': obj.district.id,
|
||||||
|
'name': obj.district.name,
|
||||||
|
} if obj.district else None
|
||||||
|
|
||||||
@@ -20,6 +20,8 @@ from core.apps.shared.views import tour_plan as tp_view
|
|||||||
from core.apps.shared.views import factory as factory_view
|
from core.apps.shared.views import factory as factory_view
|
||||||
# shared support view
|
# shared support view
|
||||||
from core.apps.shared.views import support as support_view
|
from core.apps.shared.views import support as support_view
|
||||||
|
# shared dis product
|
||||||
|
from core.apps.shared.views import dis_product as dp_view
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
@@ -88,6 +90,12 @@ urlpatterns = [
|
|||||||
path('support/', include(
|
path('support/', include(
|
||||||
[
|
[
|
||||||
path('send/', support_view.SupportCreateApiView.as_view(), name='support-create-api'),
|
path('send/', support_view.SupportCreateApiView.as_view(), name='support-create-api'),
|
||||||
|
path('list/', support_view.SupportListApiView.as_view(), name='support-list-api'),
|
||||||
]
|
]
|
||||||
))
|
)),
|
||||||
|
path('distributed_product/', include(
|
||||||
|
[
|
||||||
|
path('list/', dp_view.DistributedProductListApiView.as_view()),
|
||||||
|
]
|
||||||
|
)),
|
||||||
]
|
]
|
||||||
75
core/apps/shared/views/dis_product.py
Normal file
75
core/apps/shared/views/dis_product.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
# django
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
|
# rest framework
|
||||||
|
from rest_framework import generics, permissions
|
||||||
|
|
||||||
|
# drf yasg
|
||||||
|
from drf_yasg import openapi
|
||||||
|
from drf_yasg.utils import swagger_auto_schema
|
||||||
|
|
||||||
|
# orders
|
||||||
|
from core.apps.orders.models import DistributedProduct
|
||||||
|
|
||||||
|
# shared
|
||||||
|
from core.apps.shared.utils.response_mixin import ResponseMixin
|
||||||
|
|
||||||
|
# dashboard
|
||||||
|
from core.apps.shared.serializers.dis_product import DistributedProductListSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class DistributedProductListApiView(generics.GenericAPIView, ResponseMixin):
|
||||||
|
serializer_class = DistributedProductListSerializer
|
||||||
|
queryset = DistributedProduct.objects.all()
|
||||||
|
permission_classes = [permissions.IsAuthenticated]
|
||||||
|
|
||||||
|
@swagger_auto_schema(
|
||||||
|
manual_parameters=[
|
||||||
|
openapi.Parameter(
|
||||||
|
in_=openapi.IN_QUERY,
|
||||||
|
name="product",
|
||||||
|
description="product name bo'yicha filter",
|
||||||
|
required=False,
|
||||||
|
type=openapi.TYPE_STRING,
|
||||||
|
),
|
||||||
|
openapi.Parameter(
|
||||||
|
in_=openapi.IN_QUERY,
|
||||||
|
name="date",
|
||||||
|
description="date bo'yicha qidirish",
|
||||||
|
required=False,
|
||||||
|
type=openapi.FORMAT_DATE,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def get(self, request):
|
||||||
|
try:
|
||||||
|
product_name = request.query_params.get('product', None)
|
||||||
|
date = request.query_params.get('date', None)
|
||||||
|
|
||||||
|
queryset = self.queryset.filter(user=request.user)
|
||||||
|
|
||||||
|
# filters
|
||||||
|
if product_name is not None:
|
||||||
|
queryset = queryset.filter(product__name__istartswith=product_name)
|
||||||
|
|
||||||
|
if date is not None:
|
||||||
|
queryset = queryset.filter(date=date)
|
||||||
|
|
||||||
|
page = self.paginate_queryset(queryset)
|
||||||
|
if page is not None:
|
||||||
|
serializer = self.serializer_class(page, many=True)
|
||||||
|
return self.success_response(
|
||||||
|
data=self.get_paginated_response(serializer.data).data,
|
||||||
|
message="Malumotlar fetch qilindi",
|
||||||
|
)
|
||||||
|
serializer = self.serializer_class(queryset, many=True)
|
||||||
|
return self.success_response(
|
||||||
|
data=serializer.data,
|
||||||
|
message='Malumotlar fetch qilindi'
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return self.error_response(
|
||||||
|
data=str(e),
|
||||||
|
message='xatolik, iltimos backend dasturchiga murojaat qiling'
|
||||||
|
)
|
||||||
@@ -53,6 +53,9 @@ class DistrictCreateApiView(generics.CreateAPIView, ResponseMixin):
|
|||||||
serializer = self.serializer_class(data=request.data)
|
serializer = self.serializer_class(data=request.data)
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
name = serializer.validated_data.get('name')
|
name = serializer.validated_data.get('name')
|
||||||
|
if District.objects.filter(name=name, user=request.user).exists():
|
||||||
|
return self.failure_response(message="District qo'shib bolmadi")
|
||||||
|
|
||||||
obj = District.objects.create(name=name, user=request.user)
|
obj = District.objects.create(name=name, user=request.user)
|
||||||
return self.success_response(
|
return self.success_response(
|
||||||
data=district_serializers.DistrictSerializer(obj).data,
|
data=district_serializers.DistrictSerializer(obj).data,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from drf_yasg.utils import swagger_auto_schema
|
|||||||
# shared
|
# shared
|
||||||
from core.apps.shared.models import Support
|
from core.apps.shared.models import Support
|
||||||
from core.apps.shared.utils.response_mixin import ResponseMixin
|
from core.apps.shared.utils.response_mixin import ResponseMixin
|
||||||
from core.apps.shared.serializers.support import SupportCreateSerializer
|
from core.apps.shared.serializers.support import SupportCreateSerializer, SupportListSerializer
|
||||||
|
|
||||||
|
|
||||||
class SupportCreateApiView(generics.GenericAPIView, ResponseMixin):
|
class SupportCreateApiView(generics.GenericAPIView, ResponseMixin):
|
||||||
@@ -35,3 +35,71 @@ class SupportCreateApiView(generics.GenericAPIView, ResponseMixin):
|
|||||||
data=str(e),
|
data=str(e),
|
||||||
message='xatolik, backend dastruchiga murojaat qiling iltimos'
|
message='xatolik, backend dastruchiga murojaat qiling iltimos'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SupportListApiView(generics.GenericAPIView, ResponseMixin):
|
||||||
|
serializer_class = SupportListSerializer
|
||||||
|
queryset = Support.objects.all()
|
||||||
|
permission_classes = [permissions.IsAuthenticated]
|
||||||
|
|
||||||
|
@swagger_auto_schema(
|
||||||
|
manual_parameters=[
|
||||||
|
openapi.Parameter(
|
||||||
|
in_=openapi.IN_QUERY,
|
||||||
|
name="problem",
|
||||||
|
description="problem text bo'yicha filter",
|
||||||
|
required=False,
|
||||||
|
type=openapi.TYPE_STRING,
|
||||||
|
),
|
||||||
|
openapi.Parameter(
|
||||||
|
in_=openapi.IN_QUERY,
|
||||||
|
name="district",
|
||||||
|
description="tuman name bo'yicha filter",
|
||||||
|
required=False,
|
||||||
|
type=openapi.TYPE_STRING,
|
||||||
|
),
|
||||||
|
openapi.Parameter(
|
||||||
|
in_=openapi.IN_QUERY,
|
||||||
|
name="date",
|
||||||
|
description="date bo'yicha qidirish",
|
||||||
|
required=False,
|
||||||
|
type=openapi.FORMAT_DATE,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def get(self, request):
|
||||||
|
try:
|
||||||
|
problem = request.query_params.get('problem', None)
|
||||||
|
district_name = request.query_params.get('district', None)
|
||||||
|
date = request.query_params.get('date', None)
|
||||||
|
|
||||||
|
queryset = self.queryset.filter(user=request.user)
|
||||||
|
|
||||||
|
# filters
|
||||||
|
if problem is not None:
|
||||||
|
queryset = queryset.filter(problem__istartswith=problem)
|
||||||
|
|
||||||
|
if district_name is not None:
|
||||||
|
queryset = queryset.filter(district__name__istartswith=district_name)
|
||||||
|
|
||||||
|
if date is not None:
|
||||||
|
queryset = queryset.filter(date=date)
|
||||||
|
|
||||||
|
page = self.paginate_queryset(queryset)
|
||||||
|
if page is not None:
|
||||||
|
serializer = self.serializer_class(page, many=True)
|
||||||
|
return self.success_response(
|
||||||
|
data=self.get_paginated_response(serializer.data).data,
|
||||||
|
message="Malumotlar fetch qilindi",
|
||||||
|
)
|
||||||
|
serializer = self.serializer_class(queryset, many=True)
|
||||||
|
return self.success_response(
|
||||||
|
data=serializer.data,
|
||||||
|
message='Malumotlar fetch qilindi'
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return self.error_response(
|
||||||
|
data=str(e),
|
||||||
|
message='xatolik, iltimos backend dasturchiga murojaat qiling'
|
||||||
|
)
|
||||||
58
core/bot/main.py
Normal file
58
core/bot/main.py
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# python
|
||||||
|
import asyncio, logging, sys, os
|
||||||
|
import django
|
||||||
|
|
||||||
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.base')
|
||||||
|
django.setup()
|
||||||
|
|
||||||
|
# aiogram
|
||||||
|
from aiogram import Bot, Dispatcher, types, filters
|
||||||
|
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, WebAppInfo
|
||||||
|
|
||||||
|
# django
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
TOKEN = settings.BOT_TOKEN
|
||||||
|
|
||||||
|
bot = Bot(token=TOKEN)
|
||||||
|
dp = Dispatcher()
|
||||||
|
|
||||||
|
|
||||||
|
@dp.message(filters.CommandStart)
|
||||||
|
async def start_handler(message: types.Message):
|
||||||
|
keyboard = InlineKeyboardMarkup(
|
||||||
|
inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(
|
||||||
|
text="Tizimga kirish",
|
||||||
|
web_app=WebAppInfo(url="https://bot.meridynpharma.com")
|
||||||
|
)]
|
||||||
|
],
|
||||||
|
)
|
||||||
|
text = """
|
||||||
|
🔐 MeridynPharma ish tizimiga kirish
|
||||||
|
|
||||||
|
Hurmatli xodim,
|
||||||
|
MeridynPharma’ning ichki ish jarayonlarini avtomatlashtirish va kunlik faoliyatni samarali boshqarish uchun mo‘ljallangan Rasmiy Xodimlar Mini-Ilovasiga xush kelibsiz.
|
||||||
|
|
||||||
|
Ushbu platforma orqali sizga biriktirilgan vazifalar, hisobotlar, inventarizatsiya jarayonlari va ichki eslatmalar yagona tizim orqali boshqariladi.
|
||||||
|
|
||||||
|
▶️ Tizimga kirish tartibi
|
||||||
|
|
||||||
|
Ish faoliyatini boshlash uchun quyidagi bosqichni bajaring:
|
||||||
|
|
||||||
|
1. Quyida joylashgan “Tizimga kirish” tugmasini bosing.
|
||||||
|
yoki
|
||||||
|
2. Mini-Ilova ochilgandan so‘ng, mini ilova pastki qismida joylashgan tizimga kirish degan tugmani bosing
|
||||||
|
|
||||||
|
Agar mini-app avtomatik ochilmasa, iltimos, tugmani yana bir bor bosing.
|
||||||
|
"""
|
||||||
|
await message.answer(text, reply_markup=keyboard)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
await dp.start_polling(bot)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
|
||||||
|
asyncio.run(main())
|
||||||
@@ -31,3 +31,20 @@ def send_to_telegram(chat_id, order_id):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Telegram xatolik: {e}")
|
print(f"Telegram xatolik: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def send_message(chat_id, message):
|
||||||
|
bot_token = settings.BOT_TOKEN
|
||||||
|
|
||||||
|
try:
|
||||||
|
url = f"https://api.telegram.org/bot{bot_token}/sendMessage"
|
||||||
|
data = {
|
||||||
|
"chat_id": chat_id,
|
||||||
|
"text": message
|
||||||
|
}
|
||||||
|
response = requests.post(url, data=data)
|
||||||
|
print(response.json())
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Telegram xatosi: {e}")
|
||||||
|
return False
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
aiofiles==25.1.0
|
||||||
|
aiogram==3.23.0
|
||||||
|
aiohappyeyeballs==2.6.1
|
||||||
|
aiohttp==3.13.2
|
||||||
|
aiosignal==1.4.0
|
||||||
|
annotated-types==0.7.0
|
||||||
asgiref==3.11.0
|
asgiref==3.11.0
|
||||||
attrs==25.4.0
|
attrs==25.4.0
|
||||||
autobahn==25.11.1
|
autobahn==25.11.1
|
||||||
@@ -22,20 +28,26 @@ djangorestframework==3.16.1
|
|||||||
djangorestframework_simplejwt==5.5.1
|
djangorestframework_simplejwt==5.5.1
|
||||||
drf-yasg==1.21.11
|
drf-yasg==1.21.11
|
||||||
fonttools==4.60.1
|
fonttools==4.60.1
|
||||||
|
frozenlist==1.8.0
|
||||||
gunicorn==23.0.0
|
gunicorn==23.0.0
|
||||||
h11==0.16.0
|
h11==0.16.0
|
||||||
hyperlink==21.0.0
|
hyperlink==21.0.0
|
||||||
idna==3.11
|
idna==3.11
|
||||||
Incremental==24.11.0
|
Incremental==24.11.0
|
||||||
inflection==0.5.1
|
inflection==0.5.1
|
||||||
|
magic-filter==1.0.12
|
||||||
msgpack==1.1.2
|
msgpack==1.1.2
|
||||||
|
multidict==6.7.0
|
||||||
packaging==25.0
|
packaging==25.0
|
||||||
pillow==12.0.0
|
pillow==12.0.0
|
||||||
|
propcache==0.4.1
|
||||||
psycopg2-binary==2.9.11
|
psycopg2-binary==2.9.11
|
||||||
py-ubjson==0.16.1
|
py-ubjson==0.16.1
|
||||||
pyasn1==0.6.1
|
pyasn1==0.6.1
|
||||||
pyasn1_modules==0.4.2
|
pyasn1_modules==0.4.2
|
||||||
pycparser==2.23
|
pycparser==2.23
|
||||||
|
pydantic==2.12.5
|
||||||
|
pydantic_core==2.41.5
|
||||||
pydyf==0.11.0
|
pydyf==0.11.0
|
||||||
PyJWT==2.10.1
|
PyJWT==2.10.1
|
||||||
pyOpenSSL==25.3.0
|
pyOpenSSL==25.3.0
|
||||||
@@ -51,6 +63,7 @@ tinycss2==1.5.1
|
|||||||
tinyhtml5==2.0.0
|
tinyhtml5==2.0.0
|
||||||
Twisted==25.5.0
|
Twisted==25.5.0
|
||||||
txaio==25.9.2
|
txaio==25.9.2
|
||||||
|
typing-inspection==0.4.2
|
||||||
typing_extensions==4.15.0
|
typing_extensions==4.15.0
|
||||||
ujson==5.11.0
|
ujson==5.11.0
|
||||||
uritemplate==4.2.0
|
uritemplate==4.2.0
|
||||||
@@ -58,6 +71,6 @@ urllib3==2.5.0
|
|||||||
uvicorn==0.38.0
|
uvicorn==0.38.0
|
||||||
weasyprint==66.0
|
weasyprint==66.0
|
||||||
webencodings==0.5.1
|
webencodings==0.5.1
|
||||||
|
yarl==1.22.0
|
||||||
zope.interface==8.1.1
|
zope.interface==8.1.1
|
||||||
zopfli==0.4.0
|
zopfli==0.4.0
|
||||||
websockets
|
|
||||||
|
|||||||
@@ -2,7 +2,10 @@
|
|||||||
python3 manage.py collectstatic --noinput
|
python3 manage.py collectstatic --noinput
|
||||||
python3 manage.py migrate --noinput
|
python3 manage.py migrate --noinput
|
||||||
|
|
||||||
gunicorn config.wsgi:application -b 0.0.0.0:8000 --workers $(($(nproc) * 2 + 1))
|
gunicorn config.wsgi:application -b 0.0.0.0:8000 --workers $(($(nproc) * 2 + 1)) &
|
||||||
|
|
||||||
|
python3 core/bot/main.py &
|
||||||
|
|
||||||
|
wait
|
||||||
|
|
||||||
exit $?
|
exit $?
|
||||||
@@ -2,6 +2,10 @@
|
|||||||
python3 manage.py collectstatic --noinput
|
python3 manage.py collectstatic --noinput
|
||||||
python3 manage.py migrate --noinput
|
python3 manage.py migrate --noinput
|
||||||
|
|
||||||
uvicorn config.asgi:application --host 0.0.0.0 --port 8000 --reload --reload-dir core --reload-dir config
|
uvicorn config.asgi:application --host 0.0.0.0 --port 8000 --reload --reload-dir core --reload-dir config &
|
||||||
|
|
||||||
|
python3 core/bot/main.py &
|
||||||
|
|
||||||
|
wait
|
||||||
|
|
||||||
exit $?
|
exit $?
|
||||||
Reference in New Issue
Block a user