diff --git a/apps/authentication/services/service.py b/apps/authentication/services/service.py index 78e6893..6639db2 100644 --- a/apps/authentication/services/service.py +++ b/apps/authentication/services/service.py @@ -40,3 +40,14 @@ def get_all_org_type_child(org_type: OrganizationType = None) -> typing.Any: descendants.append(child) descendants.extend(get_all_org_type_child(child)) return descendants + + +def get_bank_info(org): + bank = org.bank_information.first() + if not bank: + return {} + return { + "credit_card": bank.card, + "sheba": f"IR{bank.sheba}", + "account": bank.account, + } diff --git a/apps/core/visibility_registry.py b/apps/core/visibility_registry.py index 6bb4e0e..f041371 100644 --- a/apps/core/visibility_registry.py +++ b/apps/core/visibility_registry.py @@ -8,6 +8,7 @@ VISIBILITY_MAP = { 'inventoryentry': 'organization', 'inventoryquotasaletransaction': 'seller_organization', 'device': 'assignment__client__organization', + 'rancher': 'organization', # 'deviceactivationcode': 'organization', # 'deviceversion': 'organization', diff --git a/apps/herd/models.py b/apps/herd/models.py index 174b18d..563ef59 100644 --- a/apps/herd/models.py +++ b/apps/herd/models.py @@ -1,6 +1,7 @@ from django.db import models from apps.authentication import models as auth_models +from apps.authentication.models import Organization from apps.core.models import BaseModel @@ -82,6 +83,13 @@ class Herd(BaseModel): class Rancher(BaseModel): + organization = models.ForeignKey( + Organization, + on_delete=models.CASCADE, + related_name='ranchers', + null=True, + help_text="connect ranchers to their specific Taavoni" # noqa + ) ranching_farm = models.CharField(max_length=150, null=True) union_name = models.CharField(max_length=50, null=True, blank=True) union_code = models.CharField(max_length=50, null=True, blank=True) diff --git a/apps/herd/web/api/v1/api.py b/apps/herd/web/api/v1/api.py index 298f3b7..e85d2fd 100644 --- a/apps/herd/web/api/v1/api.py +++ b/apps/herd/web/api/v1/api.py @@ -225,7 +225,7 @@ class RancherViewSet(BaseViewSet, RancherDashboardService, SoftDeleteMixin, view url_name='rancher_dashboard_by_quota_usage', name='rancher_dashboard_by_quota_usage' ) - def rancher_dashboard_by_quota_usage(self, request, pk=None): + def ranchers_dashboard_by_quota_usage(self, request, pk=None): """ rancher dashboard """ rancher = self.get_object() @@ -261,3 +261,37 @@ class RancherViewSet(BaseViewSet, RancherDashboardService, SoftDeleteMixin, view rancher=rancher ) return Response(rancher_dashboard_data) + + @action( + methods=['get'], + detail=False, + url_name='org_ranchers', + url_path='org_ranchers', + name='org_ranchers' + ) + def org_ranchers(self, request): + """ + list of ranchers by organization + """ + + queryset = self.get_queryset(visibility_by_org_scope=True) + + page = self.paginate_queryset(queryset) + if page is not None: # noqa + serializer = product_serializers.IncentivePlanRancherSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + return Response(status=status.HTTP_200_OK) + + @action( + methods=['get'], + detail=False, + url_name='org_ranchers_dashboard', + url_path='org_ranchers_dashboard', + name='org_ranchers_dashboard' + ) + def org_ranchers_dashboard(self, request): + """ + dashboard of ranchers report + """ + + queryset = self.get_queryset(visibility_by_org_scope=True) diff --git a/apps/herd/web/api/v1/urls.py b/apps/herd/web/api/v1/urls.py index cc8d102..23731f9 100644 --- a/apps/herd/web/api/v1/urls.py +++ b/apps/herd/web/api/v1/urls.py @@ -1,5 +1,6 @@ from django.urls import path, include from rest_framework import routers + from .api import HerdViewSet, RancherViewSet router = routers.DefaultRouter() @@ -8,4 +9,4 @@ router.register('rancher', RancherViewSet, basename='rancher') urlpatterns = [ path('api/v1/', include(router.urls)) -] \ No newline at end of file +] diff --git a/apps/pos_device/services/services.py b/apps/pos_device/services/services.py index 1d03304..b975d93 100644 --- a/apps/pos_device/services/services.py +++ b/apps/pos_device/services/services.py @@ -1,5 +1,6 @@ import typing +from apps.authentication.services.service import get_bank_info from apps.pos_device.models import Device, StakeHolders from apps.product.models import ( Quota, @@ -19,65 +20,51 @@ def pos_organizations_sharing_information( pos sharing organizations' information, device have multiple organizations (sub_accounts) for sharing money """ - stake_holders = device.stake_holders.select_related('broker', 'organization').filter() + stake_holders_qs = ( + device.stake_holders + .select_related('broker', 'organization') + .prefetch_related('organization__bank_information') + ) + + broker_values_qs = quota.broker_values.all() + + if quota_stat and quota_stat.broker_values.exists(): + broker_values_qs = broker_values_qs.filter(org_quota_stat=quota_stat) + + broker_value_map = { + bv.broker_id: bv.value + for bv in broker_values_qs + } + + if owner_org.type.key == 'AGC': + agc_stake_holder = ( + owner_org.pos_stake_holders + .filter(holders_share_amount__org_quota_stat=quota_stat) + .select_related('device') + .first() + ) + + if agc_stake_holder: + stake_holders_qs = ( + agc_stake_holder.device.stake_holders + .select_related('broker', 'organization') + .prefetch_related('organization__bank_information') + ) sharing_information_list = [] - for item in stake_holders: - if item.broker and not owner_org.type.key == 'AGC': # if stakeholder is not an agency, it is a broker - sharing_information_list.append({ - "organization_name": item.organization.name, - "bank_account": { - "credit_card": item.organization.bank_information.first().card, - "sheba": "IR" + item.organization.bank_information.first().sheba, - "account": item.organization.bank_information.first().account, - } if item.organization.bank_information.exists() else {}, - "broker": item.broker.name if item.broker else None, - "amount": quota.broker_values.filter( - broker=item.broker, - # if quota price features was edited for this organization - org_quota_stat=quota_stat if quota_stat and quota_stat.broker_values.exists() else None - ).first().value if quota.broker_values.filter(broker=item.broker).exists() else None, - # """ - # if we will need to get agencies share amount, we can use this bellow code - # - # # item.holders_share_amount.filter(quota_distribution=distribution).first().share_amount - # # if item.holders_share_amount.filter(quota_distribution=distribution).exists() else None - # """ - "agency": False, - "default_account": item.default - }) - elif owner_org.type.key == 'AGC': - agc_stake_holder = owner_org.pos_stake_holders.filter( - holders_share_amount__org_quota_stat=quota_stat, - ).first() - print(quota_stat.id) - stake_holders = agc_stake_holder.device.stake_holders.select_related( - 'broker', 'organization' - ).filter() - for item in stake_holders: - if item.broker: # if stakeholder is not an agency, it is a broker - sharing_information_list.append({ - "organization_name": item.organization.name, - "bank_account": { - "credit_card": item.organization.bank_information.first().card, - "sheba": "IR" + item.organization.bank_information.first().sheba, - "account": item.organization.bank_information.first().account, - } if item.organization.bank_information.exists() else {}, - "broker": item.broker.name if item.broker else None, - "amount": quota.broker_values.filter( - broker=item.broker, - # if quota price features was edited for this organization - org_quota_stat=quota_stat if quota_stat.broker_values.exists() else None - ).first().value if quota.broker_values.filter(broker=item.broker).exists() else None, - # """ - # if we will need to get agencies share amount, we can use this bellow code - # - # # item.holders_share_amount.filter(quota_distribution=distribution).first().share_amount - # # if item.holders_share_amount.filter(quota_distribution=distribution).exists() else None - # """ - "agency": False, - "default_account": item.default - }) + + for item in stake_holders_qs: + if not item.broker: + continue + + sharing_information_list.append({ + "organization_name": item.organization.name, + "bank_account": get_bank_info(item.organization), + "broker": item.broker.name, + "amount": broker_value_map.get(item.broker_id), + "agency": False, + "default_account": item.default, + }) # if device owner is an agency organization if owner_org.type.key == 'AGC': @@ -108,13 +95,15 @@ def agency_organization_pos_info( """ # get agency share amount - agc_share_amount = agency.pos_stake_holders.filter( - holders_share_amount__org_quota_stat=quota_stat + agc_stake_holder = ( + agency.pos_stake_holders + .filter(holders_share_amount__org_quota_stat=quota_stat) + .select_related('device') ) - agc_share_amount = agc_share_amount.first().holders_share_amount.filter( + agc_share_amount = agc_stake_holder.first().holders_share_amount.filter( org_quota_stat=quota_stat - ) if agc_share_amount.exists() else None + ) if agc_stake_holder.exists() else None agc_share_amount = agc_share_amount.first().share_amount if agc_share_amount else None diff --git a/apps/product/pos/api/v1/serializers/quota_serializers.py b/apps/product/pos/api/v1/serializers/quota_serializers.py index 1fedb9e..2a9ae08 100644 --- a/apps/product/pos/api/v1/serializers/quota_serializers.py +++ b/apps/product/pos/api/v1/serializers/quota_serializers.py @@ -274,8 +274,13 @@ class OrganizationQuotaStatsSerializer(serializers.ModelSerializer): representation['free_sale'] = instance.quota.free_sale representation['pre_sale'] = instance.quota.pre_sale - if instance.distributions: - representation['distribution'] = instance.distributions.all().order_by('-create_date').first().id + last_distribution = ( + instance.distributions + .order_by('-create_date') + .first() + ) + + representation['distribution'] = last_distribution.id if last_distribution else None if instance.quota: representation['quota'] = { diff --git a/apps/product/pos/api/v1/viewsets/quota_api.py b/apps/product/pos/api/v1/viewsets/quota_api.py index eb2c1b0..d71e7c2 100644 --- a/apps/product/pos/api/v1/viewsets/quota_api.py +++ b/apps/product/pos/api/v1/viewsets/quota_api.py @@ -229,6 +229,7 @@ class OrganizationQuotaStatsViewSet(viewsets.ModelViewSet, DynamicSearchMixin, P quotas = self.queryset.filter( Q(organization=organization), Q(quota__is_closed=False), + Q(total_amount__gt=0), ( Q(quota__pre_sale=True) | Q(quota__free_sale=True) | Q(inventory_received__gt=0) )