Skip to content

Commit

Permalink
feat: add accordion to decision box to list instalments (hl-1497) (#3515
Browse files Browse the repository at this point in the history
)

* chore: update translations

* feat: expose instalment data to single application; validate instalment status data

* fix: refactor and fix some details on instalment sums

* feat: add a new accordion for instalments in the decision box

* fix: add custom sort function for decision date (hl-1526)

* feat: use modal for instalment cancel confirm and archive application when proceeding
  • Loading branch information
sirtawast authored Nov 7, 2024
1 parent aaff375 commit 34e6201
Show file tree
Hide file tree
Showing 11 changed files with 375 additions and 186 deletions.
43 changes: 27 additions & 16 deletions backend/benefit/applications/api/v1/serializers/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,25 @@
from users.utils import get_company_from_request, get_request_user_from_context


def _get_pending_instalment(application, excluded_status=[]):
"""Get the latest pending instalment for the application"""
try:
instalments = application.calculation.instalments.filter(
instalment_number__gt=1
)
instalment = (
instalments.exclude(status__in=excluded_status)
.order_by("-due_date")
.first()
or None
)
if instalment is not None:
return InstalmentSerializer(instalment).data
except AttributeError:
return None
return None


class BaseApplicationSerializer(DynamicFieldsModelSerializer):
"""
Fields in the Company model come from YTJ/other source and are not editable by user, and are listed
Expand Down Expand Up @@ -1638,6 +1657,11 @@ class HandlerApplicationSerializer(BaseApplicationSerializer):

ahjo_error = serializers.SerializerMethodField()

pending_instalment = serializers.SerializerMethodField("get_pending_instalment")

def get_pending_instalment(self, application):
return _get_pending_instalment(application)

def get_latest_ahjo_error(self, obj) -> Union[Dict, None]:
"""Get the latest Ahjo error for the application"""
try:
Expand Down Expand Up @@ -1698,11 +1722,13 @@ class Meta(BaseApplicationSerializer.Meta):
"handler",
"handled_by_ahjo_automation",
"ahjo_error",
"pending_instalment",
]
read_only_fields = BaseApplicationSerializer.Meta.read_only_fields + [
"latest_decision_comment",
"handled_at",
"handler",
"pending_instalment",
]

@transaction.atomic
Expand Down Expand Up @@ -1954,22 +1980,7 @@ class Meta:
pending_instalment = serializers.SerializerMethodField("get_pending_instalment")

def get_pending_instalment(self, application):
"""Get the latest pending instalment for the application"""
try:
instalments = application.calculation.instalments.filter(
instalment_number__gt=1
)
instalment = (
instalments.exclude(status=InstalmentStatus.COMPLETED)
.order_by("-due_date")
.first()
or None
)
if instalment is not None:
return InstalmentSerializer(instalment).data
except AttributeError:
return None
return None
return _get_pending_instalment(application, [InstalmentStatus.COMPLETED])

ahjo_error = serializers.SerializerMethodField("get_latest_ahjo_error")

Expand Down
8 changes: 8 additions & 0 deletions backend/benefit/calculator/api/v1/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ class Meta:
"modified_at",
]

def validate_status(self, status):
if status not in InstalmentStatus.values:
raise serializers.ValidationError(
{"status": f"status must be one of {InstalmentStatus.values}"},
)

return status

status = serializers.ChoiceField(
validators=[InstalmentStatusValidator()],
choices=InstalmentStatus.choices,
Expand Down
11 changes: 9 additions & 2 deletions backend/benefit/calculator/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
InstalmentSerializer,
PreviousBenefitSerializer,
)
from calculator.enums import InstalmentStatus
from calculator.models import Instalment, PreviousBenefit
from common.permissions import BFIsHandler
from shared.audit_log.viewsets import AuditLoggingModelViewSet
Expand Down Expand Up @@ -46,9 +47,15 @@ class InstalmentView(APIView):

def patch(self, request, instalment_id):
instalment = get_object_or_404(Instalment, pk=instalment_id)

serializer = InstalmentSerializer(instalment, data=request.data)
instalment_status = request.data["status"]
serializer = InstalmentSerializer(
instalment, data={"status": instalment_status}, partial=True
)
if serializer.is_valid():
serializer.save()
if instalment_status == InstalmentStatus.CANCELLED:
application = instalment.calculation.application
application.archived = True
application.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
19 changes: 16 additions & 3 deletions frontend/benefit/handler/public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@
"cancelled": "Peruttu",
"accepted": "Hyväksytty",
"waiting": "Odottaa",
"completed": "Valmis",
"completed": "Maksettu",
"error_in_talpa": "Virhe maksussa"
},
"calculationEndDate": "Viim. tukipäivä",
Expand Down Expand Up @@ -831,7 +831,8 @@
"showDecision": "Tarkastele päätöstä",
"reportAlteration": "Tee uusi muutosilmoitus"
},
"calculation": "Laskelma"
"calculation": "Laskelma",
"instalments": "Maksuerät"
},
"alterations": {
"new": {
Expand Down Expand Up @@ -1373,7 +1374,11 @@
"result": {
"header": "Myönnettävä Helsinki-lisä",
"header2": "Arvio koostuu seuraavista tiedoista:",
"acceptedBenefit": "Myönnettävä Helsinki-lisä"
"header3": "Maksuerät",
"acceptedBenefit": "Myönnettävä Helsinki-lisä",
"firstInstalment": "Ensimmäinen maksuerä",
"secondInstalment": "Toinen maksuerä",
"total": "Yhteensä"
},
"errors": {
"trainingCompensation": {
Expand Down Expand Up @@ -1856,5 +1861,13 @@
"label": "Tila"
}
}
},
"instalments": {
"dialog": {
"cancelInstalment": {
"heading": "Maksuerän peruutus",
"text": "Oletko varma, että haluat peruuttaa {{sum}} suuruisen maksuerän hakemukselle {{details}}?"
}
}
}
}
19 changes: 16 additions & 3 deletions frontend/benefit/handler/public/locales/fi/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@
"cancelled": "Peruttu",
"accepted": "Hyväksytty",
"waiting": "Odottaa",
"completed": "Valmis",
"completed": "Maksettu",
"error_in_talpa": "Virhe maksussa"
},
"calculationEndDate": "Viim. tukipäivä",
Expand Down Expand Up @@ -831,7 +831,8 @@
"showDecision": "Tarkastele päätöstä",
"reportAlteration": "Tee uusi muutosilmoitus"
},
"calculation": "Laskelma"
"calculation": "Laskelma",
"instalments": "Maksuerät"
},
"alterations": {
"new": {
Expand Down Expand Up @@ -1373,7 +1374,11 @@
"result": {
"header": "Myönnettävä Helsinki-lisä",
"header2": "Arvio koostuu seuraavista tiedoista:",
"acceptedBenefit": "Myönnettävä Helsinki-lisä"
"header3": "Maksuerät",
"acceptedBenefit": "Myönnettävä Helsinki-lisä",
"firstInstalment": "Ensimmäinen maksuerä",
"secondInstalment": "Toinen maksuerä",
"total": "Yhteensä"
},
"errors": {
"trainingCompensation": {
Expand Down Expand Up @@ -1855,5 +1860,13 @@
"label": "Tila"
}
}
},
"instalments": {
"dialog": {
"cancelInstalment": {
"heading": "Maksuerän peruutus",
"text": "Oletko varma, että haluat peruuttaa {{sum}} suuruisen maksuerän hakemukselle {{details}}?"
}
}
}
}
19 changes: 16 additions & 3 deletions frontend/benefit/handler/public/locales/sv/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@
"cancelled": "Peruttu",
"accepted": "Hyväksytty",
"waiting": "Odottaa",
"completed": "Valmis",
"completed": "Maksettu",
"error_in_talpa": "Virhe maksussa"
},
"calculationEndDate": "Viim. tukipäivä",
Expand Down Expand Up @@ -831,7 +831,8 @@
"showDecision": "Tarkastele päätöstä",
"reportAlteration": "Tee uusi muutosilmoitus"
},
"calculation": "Laskelma"
"calculation": "Laskelma",
"instalments": "Maksuerät"
},
"alterations": {
"new": {
Expand Down Expand Up @@ -1373,7 +1374,11 @@
"result": {
"header": "Myönnettävä Helsinki-lisä",
"header2": "Arvio koostuu seuraavista tiedoista:",
"acceptedBenefit": "Myönnettävä Helsinki-lisä"
"header3": "Maksuerät",
"acceptedBenefit": "Myönnettävä Helsinki-lisä",
"firstInstalment": "Ensimmäinen maksuerä",
"secondInstalment": "Toinen maksuerä",
"total": "Yhteensä"
},
"errors": {
"trainingCompensation": {
Expand Down Expand Up @@ -1856,5 +1861,13 @@
"label": "Tila"
}
}
},
"instalments": {
"dialog": {
"cancelInstalment": {
"heading": "Maksuerän peruutus",
"text": "Oletko varma, että haluat peruuttaa {{sum}} suuruisen maksuerän hakemukselle {{details}}?"
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { APPLICATION_STATUSES } from 'benefit-shared/constants';
import {
AhjoError,
ApplicationListItemData,
Instalment,
} from 'benefit-shared/types/application';
import { IconSpeechbubbleText, Table, Tag, Tooltip } from 'hds-react';
import * as React from 'react';
Expand Down Expand Up @@ -59,18 +60,16 @@ const buildApplicationUrl = (

const getFirstInstalmentTotalAmount = (
calculatedBenefitAmount: string,
pendingInstalmentAmount?: string
pendingInstalment?: Instalment
): string | JSX.Element => {
let firstInstalment = parseInt(calculatedBenefitAmount, 10);
if (pendingInstalmentAmount) {
firstInstalment -= parseInt(pendingInstalmentAmount, 10);
if (pendingInstalment) {
firstInstalment -= parseInt(String(pendingInstalment?.amount), 10);
}
return pendingInstalmentAmount ? (
return pendingInstalment ? (
<>
<strong>
{formatFloatToCurrency(firstInstalment, null, 'fi-FI', 0)}
</strong>{' '}
/ {formatFloatToCurrency(calculatedBenefitAmount, 'EUR', 'fi-FI', 0)}
{formatFloatToCurrency(firstInstalment, null, 'fi-FI', 0)} /{' '}
{formatFloatToCurrency(calculatedBenefitAmount, 'EUR', 'fi-FI', 0)}
</>
) : (
formatFloatToCurrency(firstInstalment, 'EUR', 'fi-FI', 0)
Expand Down Expand Up @@ -328,6 +327,7 @@ const ApplicationList: React.FC<ApplicationListProps> = ({
if (inPayment) {
cols.push(
{
customSortCompareFunction: sortFinnishDate,
headerName: getHeader('decisionDate'),
key: 'decisionDate',
isSortable: true,
Expand All @@ -348,7 +348,7 @@ const ApplicationList: React.FC<ApplicationListProps> = ({
}: ApplicationListTableTransforms) =>
getFirstInstalmentTotalAmount(
String(calculatedBenefitAmount),
String(pendingInstalment?.amount) || null
pendingInstalment || null
),
}
);
Expand Down
Loading

0 comments on commit 34e6201

Please sign in to comment.