From 65c831d6a8581da3665ce81dfb15d479a9525455 Mon Sep 17 00:00:00 2001 From: Mojtaba-z Date: Tue, 26 Aug 2025 15:24:46 +0330 Subject: [PATCH] first setup of pos transaction - add provider, user, organization information of pos to login --- apps/authentication/services/service.py | 17 +++++++++++++++++ apps/core/models.py | 4 ++-- .../migrations/0063_alter_device_serial.py | 18 ++++++++++++++++++ apps/pos_device/models.py | 2 +- apps/pos_device/pos/api/v1/viewsets/device.py | 17 ++++++++++++++--- apps/warehouse/pos/api/v1/api.py | 1 + apps/warehouse/pos/api/v1/urls.py | 1 + 7 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 apps/authentication/services/service.py create mode 100644 apps/pos_device/migrations/0063_alter_device_serial.py diff --git a/apps/authentication/services/service.py b/apps/authentication/services/service.py new file mode 100644 index 0000000..87a92f3 --- /dev/null +++ b/apps/authentication/services/service.py @@ -0,0 +1,17 @@ +import typing +from apps.authentication.models import Organization + + +def get_users_of_organization(org: Organization) -> typing.Any: + """ get users of an organizations """ + user_relations = org.user_organization.all() + + users_list = [{ + 'name': f"{rel.user.first_name} {rel.user.last_name}", + 'national_code': rel.user.national_code, + 'mobile': rel.user.mobile, + 'phone': rel.user.phone, + 'address': rel.user.address + } for rel in user_relations] + + return users_list diff --git a/apps/core/models.py b/apps/core/models.py index 7037feb..b6eb829 100644 --- a/apps/core/models.py +++ b/apps/core/models.py @@ -10,14 +10,14 @@ class BaseModel(models.Model): created_by = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, - related_name="%(class)s_createddby", + related_name="%(class)s_createddby", # noqa null=True, blank=True, ) modified_by = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, - related_name="%(class)s_modifiedby", + related_name="%(class)s_modifiedby", # noqa null=True, blank=True, ) diff --git a/apps/pos_device/migrations/0063_alter_device_serial.py b/apps/pos_device/migrations/0063_alter_device_serial.py new file mode 100644 index 0000000..05803aa --- /dev/null +++ b/apps/pos_device/migrations/0063_alter_device_serial.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0 on 2025-08-26 11:52 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pos_device', '0062_stakeholders_default'), + ] + + operations = [ + migrations.AlterField( + model_name='device', + name='serial', + field=models.TextField(null=True, unique=True), + ), + ] diff --git a/apps/pos_device/models.py b/apps/pos_device/models.py index 91c4572..8513ef1 100644 --- a/apps/pos_device/models.py +++ b/apps/pos_device/models.py @@ -34,7 +34,7 @@ class Device(BaseModel): device_identity = models.CharField(max_length=25, null=True) acceptor = models.CharField(max_length=50, null=True) terminal = models.CharField(max_length=50, null=True) - serial = models.TextField(null=True) + serial = models.TextField(null=True, unique=True) password = models.CharField(max_length=25, null=True) multi_device = models.BooleanField(default=False) server_in = models.BooleanField(default=False) diff --git a/apps/pos_device/pos/api/v1/viewsets/device.py b/apps/pos_device/pos/api/v1/viewsets/device.py index af8a507..63cc371 100644 --- a/apps/pos_device/pos/api/v1/viewsets/device.py +++ b/apps/pos_device/pos/api/v1/viewsets/device.py @@ -1,4 +1,5 @@ from apps.pos_device.pos.api.v1.serializers.device import DeviceSerializer +from apps.authentication.services.service import get_users_of_organization from apps.pos_device.mixins.pos_device_mixin import POSDeviceMixin from apps.pos_device import models as pos_models from rest_framework.permissions import AllowAny @@ -49,6 +50,7 @@ class POSDeviceViewSet(viewsets.ModelViewSet, POSDeviceMixin): serial = headers_data['device-serial'] sdk = headers_data['device-sdk'] psp_name = headers_data['device-provider'] + # provider organization organization = pos_models.Organization.objects.get(en_name=psp_name) # check if device exists @@ -60,6 +62,8 @@ class POSDeviceViewSet(viewsets.ModelViewSet, POSDeviceMixin): # activate device if device: if (not device.is_activated or not device.pre_registered) and device.assigned_state: + # when device is logged in, its has an organization owner client, if not it will show error + device_owner_org = self.get_device_organization() device.is_activated = True device.save() @@ -78,13 +82,18 @@ class POSDeviceViewSet(viewsets.ModelViewSet, POSDeviceMixin): "message": "login success - session activated", "device_identity": device.device_identity, "serial": device.serial, - "device_owner": organization.name + "provider": organization.name, + "provider_users": get_users_of_organization(organization), + "device_owner": device_owner_org, + "device_owner_users": get_users_of_organization(device_owner_org) }, status=status.HTTP_200_OK) return Response({ "message": "device pre registered - unauthorized", "device_identity": device.device_identity, - "serial": device.serial + "serial": device.serial, + "provider": organization.name, + "provider_users": get_users_of_organization(organization), }, status=status.HTTP_401_UNAUTHORIZED) pre_device = pos_models.Device.objects.create( @@ -96,7 +105,9 @@ class POSDeviceViewSet(viewsets.ModelViewSet, POSDeviceMixin): return Response({ "message": "device pre-registered", - "device_identity": pre_device.device_identity + "device_identity": pre_device.device_identity, + "provider": organization.name, + "provider_users": get_users_of_organization(organization), }, status=status.HTTP_412_PRECONDITION_FAILED) @action( diff --git a/apps/warehouse/pos/api/v1/api.py b/apps/warehouse/pos/api/v1/api.py index e3fce54..0bf846a 100644 --- a/apps/warehouse/pos/api/v1/api.py +++ b/apps/warehouse/pos/api/v1/api.py @@ -75,6 +75,7 @@ class InventoryEntryViewSet(viewsets.ModelViewSet, DynamicSearchMixin, POSDevice class InventoryQuotaSaleTransactionViewSet(viewsets.ModelViewSet, DynamicSearchMixin, POSDeviceMixin): queryset = warehouse_models.InventoryQuotaSaleTransaction.objects.all() serializer_class = warehouse_serializers.InventoryQuotaSaleTransactionSerializer + permission_classes = [AllowAny] search_fields = [ "rancher__union_name", "rancher__union_code", diff --git a/apps/warehouse/pos/api/v1/urls.py b/apps/warehouse/pos/api/v1/urls.py index ee798de..707da3f 100644 --- a/apps/warehouse/pos/api/v1/urls.py +++ b/apps/warehouse/pos/api/v1/urls.py @@ -5,6 +5,7 @@ from . import api router = DefaultRouter() router.register(r'inventory_entry', api.InventoryEntryViewSet, basename='inventory_entry') +router.register(r'transaction', api.InventoryQuotaSaleTransactionViewSet, basename='transaction') urlpatterns = [ path('v1/', include(router.urls))