Skip to content

Commit

Permalink
Feature/RR-1352-Win-Breakdown (#5299)
Browse files Browse the repository at this point in the history
* Add calculation to add breakdown value to total export, non export and odi for win

* Update tests

* More tests update

* Improve get_actions function

* Improve test for deletedwinadmin and winadminform

* Add comments

* Set company contact to readonly fields

* Merge branch 'main' into feature/RR-1353-add-revision-comment-when-win-created-updated

* add new line

* Remove company and company contact from readonly as it is handled by Pawel's PR for different setting

* Refactor base export calculation
  • Loading branch information
ince-dbt authored Apr 4, 2024
1 parent e7b3721 commit 7d04233
Show file tree
Hide file tree
Showing 4 changed files with 313 additions and 39 deletions.
54 changes: 43 additions & 11 deletions datahub/export_win/admin.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import reversion
from django import forms

from django.contrib import admin
from django.contrib.admin import DateFieldListFilter
from django.forms import ModelForm
from reversion.admin import VersionAdmin

from datahub.core.admin import BaseModelAdminMixin, EXPORT_WIN_GROUP_NAME

from datahub.export_win.models import Breakdown, CustomerResponse, DeletedWin, Win, WinAdviser
from datahub.export_win.models import (
Breakdown,
CustomerResponse,
DeletedWin,
Win,
WinAdviser)


class BaseTabularInline(admin.TabularInline):
Expand Down Expand Up @@ -73,17 +80,22 @@ class BaseStackedInline(admin.StackedInline):


class CustomerResponseInlineForm(ModelForm):
"""Customer response inline form."""
"""
Customer Response in line form.
Field name is not required and field id should be read-only
"""

class Meta:
model = CustomerResponse
fields = '__all__'

def __init__(self, *args, obj=None, **kwargs):
super().__init__(*args, **kwargs)
if self.instance and self.instance.pk:
self.fields['name'].required = False
self.fields['id'].widget.attrs['readonly'] = True

instance = getattr(self, 'instance', None)
is_instance_and_pk_exist = getattr(instance, 'pk', None) is not None
self.fields['name'].required = not is_instance_and_pk_exist
self.fields['id'].widget.attrs['readonly'] = is_instance_and_pk_exist


class CustomerResponseInline(BaseStackedInline):
Expand All @@ -103,7 +115,15 @@ class Meta:

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance and self.instance.pk:
instance = self.instance
if (instance and instance.pk):
initial_values = {
'total_expected_export_value',
'total_expected_non_export_value',
'total_expected_odi_value',
}
for field_name in initial_values:
self.fields[field_name].widget = forms.TextInput(attrs={'readonly': 'readonly'})
fields_to_update = [
'cdms_reference',
'customer_email_address',
Expand Down Expand Up @@ -232,8 +252,7 @@ def get_contact_names(self, obj):
def get_actions(self, request):
"""Remove the delete selected action."""
actions = super().get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
actions.pop('delete_selected', None)
return actions

def soft_delete(self, request, queryset):
Expand All @@ -252,9 +271,22 @@ def has_delete_permission(self, request, obj=None):
return False


class WinSoftDeletedAdminForm(ModelForm):
"""Win soft deleted admin form"""

class Meta:
model = DeletedWin
fields = '__all__'

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)


@admin.register(DeletedWin)
class DeletedWinAdmin(WinAdmin):
"""Admin for Deleted Wins."""

form = WinSoftDeletedAdminForm
inlines = (BreakdownInline, CustomerResponseInline, AdvisorInline)
actions = ('undelete',)

Expand All @@ -275,9 +307,6 @@ def has_add_permission(self, request, obj=None):
def has_delete_permission(self, request, obj=None):
return False

def has_change_permission(self, request, obj=None):
return False

def has_view_permission(self, request, obj=None):
"""Set the desired user group to access view deleted win"""
if (
Expand All @@ -286,3 +315,6 @@ def has_view_permission(self, request, obj=None):
):
return True
return False

def has_change_permission(self, request, obj=None):
return False
46 changes: 44 additions & 2 deletions datahub/export_win/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
from django.conf import settings

from django.db import models, transaction
from django.db.models import Max
from django.db.models import Max, Sum
from django.db.models.signals import post_save
from django.dispatch import receiver

from datahub.company.models import (
Advisor,
Company,
Contact,
ExportExperience,
)
from datahub.core import reversion
from datahub.core import constants, reversion
from datahub.core.models import BaseModel, BaseOrderedConstantModel
from datahub.export_win.constants import EXPORT_WINS_LEGACY_ID_START_VALUE
from datahub.metadata.models import (
Expand Down Expand Up @@ -411,6 +413,13 @@ class Win(BaseModel):

objects = BaseExportWinSoftDeleteManager()

def save(self, *args, **kwargs):
calc_total = _calculate_totals_for_export_win(self)
self.total_expected_export_value = calc_total['total_export_value']
self.total_expected_non_export_value = calc_total['total_non_export_value']
self.total_expected_odi_value = calc_total['total_odi_value']
super().save(*args, **kwargs)


class Breakdown(BaseModel, BaseLegacyModel):
"""Win breakdown."""
Expand Down Expand Up @@ -656,3 +665,36 @@ class DeletedWin(Win):

class Meta:
proxy = True


def _calculate_totals_for_export_win(win_instance):
"""Base class for Total Export, Non Export and ODI"""
export_type_value = constants.BreakdownType.export.value
non_export_value = constants.BreakdownType.non_export.value
odi_value = constants.BreakdownType.odi.value
return {
'total_export_value': win_instance.breakdowns.filter(
type_id=export_type_value.id).aggregate(
total_export_value=Sum('value'),
)['total_export_value'] or 0,
'total_non_export_value': win_instance.breakdowns.filter(
type_id=non_export_value.id).aggregate(
total_non_export_value=Sum('value'),
)['total_non_export_value'] or 0,
'total_odi_value': win_instance.breakdowns.filter(
type_id=odi_value.id).aggregate(
total_odi_value=Sum('value'),
)['total_odi_value'] or 0,
}


@receiver(post_save, sender=Breakdown)
def update_total_values(sender, instance, **kwargs):
"""Save the right total values"""
win = instance.win

calc_total = _calculate_totals_for_export_win(win)
win.total_expected_export_value = calc_total['total_export_value']
win.total_expected_non_export_value = calc_total['total_non_export_value']
win.total_expected_odi_value = calc_total['total_odi_value']
win.save()
Loading

0 comments on commit 7d04233

Please sign in to comment.