@@ -1,4 +1,3 @@ -from decimal import Decimal from typing import Any, OrderedDict, Tuple from django.utils.translation import gettext_lazy as _ @@ -35,22 +34,13 @@ class BusinessAccountService: cls, user: CustomUserModel, host: BusinessUserHost, - status: Tuple[str, Any] | None = None, - account_privileges: Tuple[str, Any] | None = None, - token_limit: Decimal | None = None, + account_privileges: str, ): - account: BusinessAccount = BusinessAccount.objects.create( + account, _ = BusinessAccount.objects.update_or_create( user=user, parent_company=host, + defaults={'account_privileges': account_privileges}, ) - - if status is not None: - account.acceptance_status = status - if account_privileges is not None: - account.account_privileges = account_privileges - if token_limit is not None: - account.token_limit = token_limit - account.save() return cls(account) @classmethod @@ -84,14 +74,6 @@ class BusinessAccountService: def reject(self): self.update_status(InvitationStatus.REJECTED) - def update_limit(self, new_balance: Decimal | None): - self.account.token_limit = new_balance - self.account.save() - - def update_privileges(self, new_privileges: str): - self.account.account_privileges = new_privileges - self.account.save() - def update_user_password(self, request: Request): serializer = ChangePasswordSerializer(data=request.data) serializer.is_valid(raise_exception=True) @@ -1,12 +1,13 @@ from decimal import Decimal from typing import Any, Tuple -from django.db import IntegrityError -from django.utils.translation import gettext_lazy as _ from rest_framework.request import Request from authentication.exceptions import business_host_exceptions -from authentication.exceptions.business_account import BusinessAccountNotFound, AdminReinviteForbidden +from authentication.exceptions.business_account import ( + AdminReinviteForbidden, + BusinessAccountNotFound, +) from authentication.exceptions.business_host_exceptions import AlreadyAccount, InviteeHasPlan from authentication.exceptions.business_host_exceptions.already_host import ( AlreadyHost, @@ -16,7 +17,6 @@ from authentication.models import ( BusinessUserHost, CustomUserModel, ) -from authentication.models.choices import InvitationStatus from authentication.selectors.account_status_selector import ( AccountStatusSelector, ) @@ -28,13 +28,11 @@ from authentication.selectors.business_host_selector import ( ) from authentication.selectors.user_selector import UserSelector from authentication.serializers import ( - AccountDataUpdateSerializer, AddModelsSerializer, BusinessAccountDataSerializer, BusinessHostSerializer, BusinessHostUpdateSerializer, DeleteBusinessAccountSerializer, - DeletedAccountDataSerializer, DeleteModelsSerializer, NewBusinessAccountSerializer, NewBusinessHostSerializer, @@ -56,34 +54,18 @@ class BusinessHostService: self.user = user def create_account( - self, - email: str, - host: BusinessUserHost, - token_limit: Decimal | None = None, - account_privileges: Tuple[str, Any] | None = None, + self, email: str, host: BusinessUserHost, account_privileges: str ) -> BusinessAccountService: password = generate_token(15) user = CustomUserModel.objects.create_user(email=email, password=password) - user.save() PaymentPlanService(user).subscribe_user_to_plan(PaymentPlan.objects.get(price=0, is_corporate=False)) - account_service = BusinessAccountService.create( - user, - host, - account_privileges=account_privileges, - ) - if token_limit is not None: - account_service.update_limit(token_limit) + account_service = BusinessAccountService.create(user, host, account_privileges=account_privileges) EmailService.send_corporate_greeting_email(account_service.account, password) return account_service - def create_existing( - self, - email: str, - token_limit: Decimal | None = None, - account_privileges: Tuple[str, Any] | None = None, - ) -> BusinessAccountService: + def create_existing(self, email: str, account_privileges: str) -> BusinessAccountService: company = self.user.host or self.user.employee.parent_company try: user = UserSelector.get_by_email(email.lower()) @@ -94,22 +76,12 @@ class BusinessHostService: if PaymentPlanSelector(user).is_plan_paid(): raise InviteeHasPlan except CustomUserModel.DoesNotExist: - return self.create_account( - email=email, - host=company, - token_limit=token_limit, - account_privileges=account_privileges, - ) - try: - account_service = BusinessAccountService.create( - user, - company, - account_privileges=account_privileges, - ) - except IntegrityError: - account_service = BusinessAccountService.from_user(user) - if token_limit is not None: - account_service.update_limit(token_limit) + return self.create_account(email=email, host=company, account_privileges=account_privileges) + account_service = BusinessAccountService.create( + user, + company, + account_privileges=account_privileges, + ) if not user.is_deleted: EmailService.send_corporate_invitation_email(account_service.account, company) else: @@ -128,51 +100,22 @@ class BusinessHostService: account = self.create_existing(**serializer.validated_data).account return BusinessAccountDataSerializer(account, context={'account_type': 'business_account'}) - def update_token_limit( - self, - user: CustomUserModel, - amount: Decimal, - ): - BusinessAccountSelector.from_user(user, company=self.user.host_account).to_service().update_limit( - amount - ) - def update_user_invitation_status(self, user: CustomUserModel, new_status: Tuple[str, Any]): BusinessAccountSelector.from_user(user, company=self.user.host_account).to_service().update_status( new_status ) - def update_privileges(self, user: CustomUserModel, new_privileges: str): - BusinessAccountSelector.from_user( - user, company=self.user.host_account - ).to_service().update_privileges(new_privileges) - - def update(self, request: Request, **kwargs): - serializer = AccountDataUpdateSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - - user_email = kwargs.get('user_email', None) - if user_email is None: - raise Exception(_('No user_email is provided')) - - user = UserSelector.get_by_email(user_email) - if not AccountStatusSelector(user).is_business_account(): - raise Exception("Business Account for this user doesn't exist") - if token_limit := serializer.validated_data.get('token_limit', None): - self.update_token_limit( - user, - token_limit, - ) - if status := serializer.validated_data.get('status', False): - self.update_user_invitation_status(user, status) - if privileges := serializer.validated_data.get('account_privileges', None): - self.update_privileges(user, privileges) - - account_type = UserSelector(user).check_account_type() - if status == InvitationStatus.CANCELLED: - return DeletedAccountDataSerializer(user, context={'account_type': 'regular'}) - - return BusinessAccountDataSerializer(user.business_account, context={'account_type': account_type}) + def update(self, email: str, token_limit: Decimal | None, privileges: str) -> BusinessAccount: + business_account = UserSelector.get_by_email(email).employee + if not business_account: + raise BusinessAccountNotFound + company = self.user.host or self.user.employee.parent_company + if business_account.parent_company != company: + raise AlreadyAccount + business_account.token_limit = token_limit + business_account.account_privileges = privileges + business_account.save() + return business_account def update_self(self, request: Request, serialize: bool = True) -> BusinessHostSerializer: serializer = BusinessHostUpdateSerializer(data=request.data) @@ -157,12 +157,6 @@ class UserDetailSerializer(serializers.Serializer): class NewBusinessAccountSerializer(serializers.Serializer): email = serializers.EmailField() - token_limit = serializers.DecimalField( - max_digits=50, - decimal_places=2, - required=False, - default=None, - ) account_privileges = serializers.ChoiceField( choices=AccountPrivileges.choices, default=AccountPrivileges.REGULAR ) @@ -191,16 +185,6 @@ class BusinessHostUpdateSerializer(serializers.Serializer): token_cap = serializers.DecimalField(max_digits=15, decimal_places=2, required=False) -class DeletedAccountDataSerializer(serializers.Serializer): - email = serializers.EmailField() - account_type = serializers.SerializerMethodField() - created_at = serializers.DateTimeField() - updated_at = serializers.DateTimeField() - - def get_account_type(self, obj): - return self.context.get('account_type') - - class NeuronModelStatisticsSerialiser(serializers.Serializer): title = serializers.CharField() spent_amount = serializers.SerializerMethodField() @@ -281,7 +265,6 @@ class ChangeInvitationStatusSerializer(serializers.Serializer): class AccountDataUpdateSerializer(serializers.Serializer): - status = serializers.ChoiceField(choices=InvitationStatus.choices, required=False) token_limit = serializers.DecimalField(max_digits=50, decimal_places=2, default=None) account_privileges = serializers.ChoiceField( choices=AccountPrivileges.choices, default=AccountPrivileges.REGULAR @@ -618,13 +618,21 @@ class HostInvitationAPIView(APIView): request=AccountDataUpdateSerializer, responses={200: BusinessAccountDataSerializer}, ) - def put(self, request, *args, **kwargs): + def put(self, request, user_email : str, *args, **kwargs): """Update company sub-user.""" try: - result = BusinessHostService(self.request.user).update(request, **kwargs) + serializer = AccountDataUpdateSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + data = serializer.validated_data + employee = BusinessHostService(self.request.user).update( + user_email, data['token_limit'], data['account_privileges'] + ) + result = BusinessAccountDataSerializer( + employee, context={'account_type': employee.user.account_type} + ) return Response(result.data, status=status.HTTP_200_OK) - except Exception as err: - return Response({'detail': f'{err}'}, status=status.HTTP_400_BAD_REQUEST) + except Exception as exc: + return Response({'detail': f'{exc}'}, status=status.HTTP_400_BAD_REQUEST) class AccountInvitationAPIView(APIView):