diff --git a/backend/benefit/applications/api/v1/talpa_integration_views.py b/backend/benefit/applications/api/v1/talpa_integration_views.py index 7dde85bfc8..7baf4c5cbf 100644 --- a/backend/benefit/applications/api/v1/talpa_integration_views.py +++ b/backend/benefit/applications/api/v1/talpa_integration_views.py @@ -94,6 +94,7 @@ def _handle_successful_applications( log_message="instalment was read by TALPA and marked as paid", is_success=True, ) + else: applications = self._get_applications(application_numbers) self.update_application_and_related_batch( @@ -164,8 +165,9 @@ def do_status_updates_based_on_instalments( """ After receiving the callback from Talpa, query the currently due instalments of the successful applications and update the status of the instalments. - If the instalmentis 1/1 or 2/2, e.g the final instalment, - update the application status, batch status and set the application as archived + If the instalments 1/1 or 2/2, e.g the final instalment, + update the application status, batch status to SENT_TO_TALPA. + Always set the application as archived after the first instalment is succesfully sent to talpa. """ for application in applications: instalment = application.calculation.instalments.get( @@ -176,6 +178,20 @@ def do_status_updates_based_on_instalments( instalment.save() if is_success: + # after 1st instalment is sent to talpa, + # update the application status, + # batch status and set the application as archived + application.talpa_status = ( + ApplicationTalpaStatus.PARTIALLY_SENT_TO_TALPA + ) + application.archived = True + application.save() + + application.batch.status = ( + ApplicationBatchStatus.PARTIALLY_SENT_TO_TALPA + ) + application.batch.save() + if application.number_of_instalments == 1 or ( application.number_of_instalments == 2 and instalment.instalment_number == 2 @@ -186,7 +202,6 @@ def do_status_updates_based_on_instalments( self.write_to_audit_log(application, ip_address, log_message) def update_after_all_instalments_are_sent(self, application: Application): - application.archived = True application.talpa_status = ApplicationTalpaStatus.SUCCESSFULLY_SENT_TO_TALPA application.save() application.batch.status = ApplicationBatchStatus.SENT_TO_TALPA diff --git a/backend/benefit/applications/enums.py b/backend/benefit/applications/enums.py index dd8e5cfd0b..e88672696a 100644 --- a/backend/benefit/applications/enums.py +++ b/backend/benefit/applications/enums.py @@ -130,6 +130,9 @@ class ApplicationBatchStatus(models.TextChoices): "Returned from Ahjo without decision" ) # Theoretically possible: means that a decision was not made SENT_TO_TALPA = "sent_to_talpa", _("Sent to Talpa") + PARTIALLY_SENT_TO_TALPA = "partially_sent_to_talpa", _( + "One of two instalments sent to Talpa" + ) COMPLETED = "completed", _("Processing is completed") REJECTED_BY_TALPA = "rejected_by_talpa", _("Rejected by Talpa") CANCELLED = "cancelled", _("Cancelled") @@ -138,6 +141,9 @@ class ApplicationBatchStatus(models.TextChoices): class ApplicationTalpaStatus(models.TextChoices): NOT_PROCESSED_BY_TALPA = "not_sent_to_talpa", _("Not sent to Talpa") REJECTED_BY_TALPA = "rejected_by_talpa", _("Rejected by Talpa") + PARTIALLY_SENT_TO_TALPA = "partially_sent_to_talpa", _( + "One of two instalments sent to Talpa" + ) SUCCESSFULLY_SENT_TO_TALPA = "successfully_sent_to_talpa", _( "Successfully sent to Talpa" ) diff --git a/backend/benefit/applications/migrations/0090_alter_application_talpa_status_and_more.py b/backend/benefit/applications/migrations/0090_alter_application_talpa_status_and_more.py new file mode 100644 index 0000000000..bafa9f13dc --- /dev/null +++ b/backend/benefit/applications/migrations/0090_alter_application_talpa_status_and_more.py @@ -0,0 +1,67 @@ +# Generated by Django 4.2.11 on 2024-12-02 12:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("applications", "0089_ahjodecisionproposaldraft_signer_id_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="application", + name="talpa_status", + field=models.CharField( + choices=[ + ("not_sent_to_talpa", "Not sent to Talpa"), + ("rejected_by_talpa", "Rejected by Talpa"), + ("partially_sent_to_talpa", "One of two instalments sent to Talpa"), + ("successfully_sent_to_talpa", "Successfully sent to Talpa"), + ], + default="not_sent_to_talpa", + max_length=64, + verbose_name="talpa_status", + ), + ), + migrations.AlterField( + model_name="applicationbatch", + name="status", + field=models.CharField( + choices=[ + ("draft", "Draft"), + ( + "exported_ahjo_report", + "Ahjo report created, not yet sent to AHJO", + ), + ("awaiting_ahjo_decision", "Sent to Ahjo, decision pending"), + ("accepted", "Accepted in Ahjo"), + ("rejected", "Rejected in Ahjo"), + ("returned", "Returned from Ahjo without decision"), + ("sent_to_talpa", "Sent to Talpa"), + ("partially_sent_to_talpa", "One of two instalments sent to Talpa"), + ("completed", "Processing is completed"), + ("rejected_by_talpa", "Rejected by Talpa"), + ("cancelled", "Cancelled"), + ], + default="draft", + max_length=64, + verbose_name="status of batch", + ), + ), + migrations.AlterField( + model_name="historicalapplication", + name="talpa_status", + field=models.CharField( + choices=[ + ("not_sent_to_talpa", "Not sent to Talpa"), + ("rejected_by_talpa", "Rejected by Talpa"), + ("partially_sent_to_talpa", "One of two instalments sent to Talpa"), + ("successfully_sent_to_talpa", "Successfully sent to Talpa"), + ], + default="not_sent_to_talpa", + max_length=64, + verbose_name="talpa_status", + ), + ), + ] diff --git a/backend/benefit/applications/tests/test_talpa_integration.py b/backend/benefit/applications/tests/test_talpa_integration.py index 36adce9bd5..83c05d7d00 100644 --- a/backend/benefit/applications/tests/test_talpa_integration.py +++ b/backend/benefit/applications/tests/test_talpa_integration.py @@ -204,15 +204,17 @@ def test_talpa_callback_success( if instalments_enabled: for i in range(number_of_instalments): + status = InstalmentStatus.ACCEPTED due_date = datetime.now(timezone.utc).date() if i == 1: + status = InstalmentStatus.WAITING due_date = timezone.now() + timedelta(days=181) Instalment.objects.create( calculation=decided_application.calculation, amount=decimal.Decimal("123.45"), instalment_number=i + 1, - status=InstalmentStatus.ACCEPTED, + status=status, due_date=due_date, ) @@ -248,8 +250,10 @@ def test_talpa_callback_success( due_date__lte=timezone.now().date() ) assert len(instalments) == 1 + for instalment in instalments: assert instalment.status == InstalmentStatus.PAID + if number_of_instalments == 1: assert ( decided_application.talpa_status @@ -259,6 +263,28 @@ def test_talpa_callback_success( assert ( decided_application.batch.status == ApplicationBatchStatus.SENT_TO_TALPA ) + else: + # If two instalments test that the application is partially sent to talpa + + instalment_1 = decided_application.calculation.instalments.get( + instalment_number=1 + ) + assert instalment_1.status == InstalmentStatus.PAID + + instalment_2 = decided_application.calculation.instalments.get( + instalment_number=2 + ) + assert instalment_2.status == InstalmentStatus.WAITING + + assert ( + decided_application.talpa_status + == ApplicationTalpaStatus.PARTIALLY_SENT_TO_TALPA + ) + assert decided_application.archived is True + assert ( + decided_application.batch.status + == ApplicationBatchStatus.PARTIALLY_SENT_TO_TALPA + ) else: assert ( decided_application.talpa_status @@ -267,7 +293,7 @@ def test_talpa_callback_success( assert decided_application.batch.status == ApplicationBatchStatus.SENT_TO_TALPA - assert decided_application.archived is True + assert decided_application.archived is True @pytest.mark.parametrize(