pos device login depoyment
This commit is contained in:
@@ -48,7 +48,7 @@ class PosDeviceValidationMiddleware:
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
def validate_request(self, request):
|
def validate_request(self, request):
|
||||||
headers = request.headers.kiani
|
headers = request.headers
|
||||||
data = {key: headers.get(key) for key in self.REQUIRED_HEADERS}
|
data = {key: headers.get(key) for key in self.REQUIRED_HEADERS}
|
||||||
|
|
||||||
missing = [key for key, value in data.items() if not value]
|
missing = [key for key, value in data.items() if not value]
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# Generated by Django 5.0 on 2025-08-17 11:41
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('pos_device', '0058_rename_assigned_device_assigned_state'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='device',
|
||||||
|
name='pre_registered',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='device',
|
||||||
|
name='acceptor',
|
||||||
|
field=models.CharField(max_length=50, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='device',
|
||||||
|
name='terminal',
|
||||||
|
field=models.CharField(max_length=50, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -32,8 +32,8 @@ class ProviderCompany(BaseModel):
|
|||||||
|
|
||||||
class Device(BaseModel):
|
class Device(BaseModel):
|
||||||
device_identity = models.CharField(max_length=25, null=True)
|
device_identity = models.CharField(max_length=25, null=True)
|
||||||
acceptor = models.CharField(max_length=50)
|
acceptor = models.CharField(max_length=50, null=True)
|
||||||
terminal = models.CharField(max_length=50)
|
terminal = models.CharField(max_length=50, null=True)
|
||||||
serial = models.TextField(null=True)
|
serial = models.TextField(null=True)
|
||||||
password = models.CharField(max_length=25, null=True)
|
password = models.CharField(max_length=25, null=True)
|
||||||
multi_device = models.BooleanField(default=False)
|
multi_device = models.BooleanField(default=False)
|
||||||
@@ -41,7 +41,7 @@ class Device(BaseModel):
|
|||||||
latitude = models.FloatField(default=0)
|
latitude = models.FloatField(default=0)
|
||||||
longitude = models.FloatField(default=0)
|
longitude = models.FloatField(default=0)
|
||||||
is_activated = models.BooleanField(default=False)
|
is_activated = models.BooleanField(default=False)
|
||||||
# pre_registered = models.BooleanField(default=False)
|
pre_registered = models.BooleanField(default=False)
|
||||||
organization = models.ForeignKey(
|
organization = models.ForeignKey(
|
||||||
Organization,
|
Organization,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
@@ -57,8 +57,8 @@ class Device(BaseModel):
|
|||||||
""" generate identity for every device """
|
""" generate identity for every device """
|
||||||
prefix = "POS"
|
prefix = "POS"
|
||||||
while True:
|
while True:
|
||||||
number_part = ''.join(random.choices(string.digits, k=6))
|
number_part = ''.join(random.choices(string.digits, k=9))
|
||||||
code = f"{prefix}{number_part}"
|
code = f"{number_part}"
|
||||||
if not Device.objects.filter(device_identity=code).exists():
|
if not Device.objects.filter(device_identity=code).exists():
|
||||||
return code
|
return code
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
from apps.pos_device import models as pos_models
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = pos_models.Device
|
||||||
|
fields = '__all__'
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from rest_framework.routers import DefaultRouter
|
from rest_framework.routers import DefaultRouter
|
||||||
from .viewsets.device import TestViewSet
|
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
router.register('test', TestViewSet, basename='test')
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('v1/', include(router.urls))
|
path('v1/', include(router.urls))
|
||||||
|
|||||||
@@ -1,8 +1,108 @@
|
|||||||
from rest_framework import viewsets
|
from apps.pos_device.pos.api.v1.serializers.device import DeviceSerializer
|
||||||
|
from apps.pos_device import models as pos_models
|
||||||
|
from rest_framework.permissions import AllowAny
|
||||||
|
from rest_framework.decorators import action
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
from common.generics import get_client_ip
|
||||||
|
from rest_framework import viewsets
|
||||||
|
from django.db import transaction
|
||||||
|
from rest_framework import status
|
||||||
|
|
||||||
|
|
||||||
class TestViewSet(viewsets.ModelViewSet):
|
class POSDeviceViewSet(viewsets.ModelViewSet):
|
||||||
|
device_queryset = pos_models.Device.objects.all()
|
||||||
|
session_queryset = pos_models.Sessions.objects.all()
|
||||||
|
serializer_class = DeviceSerializer
|
||||||
|
HEADERS = [
|
||||||
|
'device-mac', 'device-serial', 'device-name',
|
||||||
|
'device-sdk', 'device-version',
|
||||||
|
'device-lng', 'device-lot', 'device-provider', # noqa
|
||||||
|
'device-vname', # noqa
|
||||||
|
]
|
||||||
|
permission_classes = [AllowAny]
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
@action(
|
||||||
return Response("Hello from the outsiiiiiiiiide") # noqa
|
methods=['post'],
|
||||||
|
detail=False,
|
||||||
|
url_path='login',
|
||||||
|
url_name='login',
|
||||||
|
name='login'
|
||||||
|
)
|
||||||
|
@transaction.atomic
|
||||||
|
def login(self, request):
|
||||||
|
""" login of pos device """
|
||||||
|
|
||||||
|
# convert headers to dictionary
|
||||||
|
headers_data = {key: request.headers.get(key) for key in self.HEADERS}
|
||||||
|
|
||||||
|
serial = headers_data['device-serial']
|
||||||
|
sdk = headers_data['device-sdk']
|
||||||
|
psp_name = headers_data['device-provider']
|
||||||
|
organization = pos_models.Organization.objects.get(en_name=psp_name)
|
||||||
|
|
||||||
|
# check if device exists
|
||||||
|
if 'device_identity' in request.data.keys():
|
||||||
|
device = self.device_queryset.filter(device_identity=request.data['device_identity'])
|
||||||
|
else:
|
||||||
|
device = self.device_queryset.filter(serial=serial).first()
|
||||||
|
|
||||||
|
# activate device
|
||||||
|
if device:
|
||||||
|
if not device.is_activated:
|
||||||
|
device.is_activated = True
|
||||||
|
device.save()
|
||||||
|
|
||||||
|
session = pos_models.Sessions.objects.create(
|
||||||
|
device=device,
|
||||||
|
password=device.password,
|
||||||
|
version=headers_data['device-version'],
|
||||||
|
mac=headers_data['device-mac'],
|
||||||
|
ip=get_client_ip(request),
|
||||||
|
sdk=headers_data['device-sdk'],
|
||||||
|
serial=headers_data['device-serial'],
|
||||||
|
latitude=headers_data['device-lot'],
|
||||||
|
longitude=headers_data['device-lng'],
|
||||||
|
)
|
||||||
|
return Response({
|
||||||
|
"message": "login success - session activated",
|
||||||
|
"device_identity": device.device_identity,
|
||||||
|
"serial": device.serial
|
||||||
|
}, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
pre_device = pos_models.Device.objects.create(
|
||||||
|
serial=serial,
|
||||||
|
sdk=sdk,
|
||||||
|
organization=organization,
|
||||||
|
pre_regitered=True,
|
||||||
|
is_activated=False
|
||||||
|
)
|
||||||
|
|
||||||
|
return Response({
|
||||||
|
"message": "device pre-registered",
|
||||||
|
"device_identity": pre_device.device_identity
|
||||||
|
}, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
@action(
|
||||||
|
methods=['post'],
|
||||||
|
detail=False,
|
||||||
|
url_path='merge_devices',
|
||||||
|
url_name='merge_devices',
|
||||||
|
name='merge_devices'
|
||||||
|
)
|
||||||
|
@transaction.atomic
|
||||||
|
def merge_devices(self, request):
|
||||||
|
""" merge pre register device & device has registered by psp user """
|
||||||
|
|
||||||
|
pre_device = self.device_queryset.get(device_identity=request.data['pre_device'])
|
||||||
|
real_device = self.device_queryset.get(device_identity=request.data['real_device'])
|
||||||
|
|
||||||
|
real_device.device_identity = pre_device.device_identity
|
||||||
|
real_device.save()
|
||||||
|
|
||||||
|
pre_device.delete()
|
||||||
|
|
||||||
|
return Response({
|
||||||
|
"message": "device merged successfully",
|
||||||
|
"device_identity": real_device.device_identity,
|
||||||
|
"serial": real_device.serial
|
||||||
|
})
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
# Your services go here
|
|
||||||
1
apps/pos_device/services/helper_service.py
Normal file
1
apps/pos_device/services/helper_service.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
|
from .pos.api.v1.viewsets import device
|
||||||
|
from rest_framework.routers import DefaultRouter
|
||||||
|
|
||||||
|
router = DefaultRouter()
|
||||||
|
router.register(r'', device.POSDeviceViewSet, basename='auth')
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('web/', include('apps.pos_device.web.api.v1.urls')),
|
path('web/', include('apps.pos_device.web.api.v1.urls')),
|
||||||
path('pos/', include('apps.pos_device.pos.api.v1.urls'))
|
path('pos/', include('apps.pos_device.pos.api.v1.urls')),
|
||||||
|
path('auth/', include(router.urls)),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -9,3 +9,8 @@ def base64_to_image_file(base64_string, filename="image.jpg"):
|
|||||||
img_format, img_str = base64_string.split(';base64,') # split before & after of ';base64,'
|
img_format, img_str = base64_string.split(';base64,') # split before & after of ';base64,'
|
||||||
ext = img_format.split('/')[-1] # split format of file
|
ext = img_format.split('/')[-1] # split format of file
|
||||||
return ContentFile(base64.b64decode(img_str), name=f"{filename}.{ext}"), ext
|
return ContentFile(base64.b64decode(img_str), name=f"{filename}.{ext}"), ext
|
||||||
|
|
||||||
|
|
||||||
|
def get_client_ip(request): # noqa
|
||||||
|
forwarded = request.META.get('HTTP_X_FORWARDED_FOR')
|
||||||
|
return forwarded.split(',')[0] if forwarded else request.META.get('REMOTE_ADDR')
|
||||||
|
|||||||
Reference in New Issue
Block a user