Skip to content

Commit

Permalink
Merge pull request #1400 from betagouv/1395-double-snapshot
Browse files Browse the repository at this point in the history
Valide automatiquement les déclarations ayant des doublons du snapshot "SUBMIT"
  • Loading branch information
pletelli authored Dec 20, 2024
2 parents 95815a6 + 9578fb4 commit d6cfc45
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 7 deletions.
15 changes: 8 additions & 7 deletions config/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@

from django.conf import settings
from django.db import transaction
from django.db.models import Count, Max
from django.db.models import Count, F, Max, Q
from django.utils import timezone

from dateutil.relativedelta import relativedelta
from viewflow import fsm

from config import email
from data.etl.transformer_loader import ETL_OPEN_DATA_DECLARATIONS
from data.models import Declaration, Snapshot

from .celery import app
from data.etl.transformer_loader import ETL_OPEN_DATA_DECLARATIONS

logger = logging.getLogger(__name__)
Status = Declaration.DeclarationStatus
Expand Down Expand Up @@ -145,11 +145,12 @@ def approve_declarations():
article__in=[Declaration.Article.ARTICLE_15, Declaration.Article.ARTICLE_15_HIGH_RISK_POPULATION],
)
# Plus précisement, seulement les déclarations qui n'ont pas été traitées ni touchées par l'instruction,
# et donc ont seulement un snapshot : celui créé par la soumission DRAFT => AWAITING_INSTRUCTION
.annotate(snapshot_count=Count("snapshots"))
.filter(snapshot_count=1)
# On vérifie que le snapshot en question soit bien du type "SUBMIT"
.filter(snapshots__action=Snapshot.SnapshotActions.SUBMIT)
# et donc ont seulement des snapshots type "SUBMIT" (créés par le passage DRAFT => AWAITING_INSTRUCTION)
.annotate(
total_snapshot_count=Count("snapshots"),
submit_snapshots_count=Count("snapshots", filter=Q(snapshots__action=Snapshot.SnapshotActions.SUBMIT)),
)
.filter(total_snapshot_count=F("submit_snapshots_count"))
# Et finalement on ne prend que celles soumises au moins il y a deux mois
.annotate(submission_date=Max("snapshots__creation_date"))
.filter(submission_date__lt=cutoff_delta)
Expand Down
44 changes: 44 additions & 0 deletions config/tests/test_automatic_approval.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,50 @@ def test_awaiting_declaration_approved_art_15(self, _):
latest_snapshot_hrp = declaration_high_risk_population.snapshots.latest("creation_date")
self.assertEqual(latest_snapshot_hrp.action, Snapshot.SnapshotActions.AUTOMATICALLY_AUTHORIZE)

def test_double_submission_declaration_approved_art_15(self, _):
"""
Dans certains cas, un·e admin peut remettre la déclaration à l'état brouillon depuis
l'admin afin que le pro puisse corriger une erreur repéré tardivement. Dans ces cas,
deux snapshots type SUBMIT sont créés. Le bot doit quand même approuver ces déclarations.
Plus d'infos : https://github.com/betagouv/complements-alimentaires/issues/1395
"""
declaration_15 = AwaitingInstructionDeclarationFactory(overriden_article=Declaration.Article.ARTICLE_15)

# Double soumission
TestAutomaticApproval._create_submission_snapshot(declaration_15)
TestAutomaticApproval._create_submission_snapshot(declaration_15)

approve_declarations()
declaration_15.refresh_from_db()

self.assertEqual(declaration_15.status, Declaration.DeclarationStatus.AUTHORIZED)
latest_snapshot_15 = declaration_15.snapshots.latest("creation_date")
self.assertEqual(latest_snapshot_15.action, Snapshot.SnapshotActions.AUTOMATICALLY_AUTHORIZE)

def test_non_submission_snapshots_not_approved_art_15(self, _):
"""
Si au moins un snapshot est présent avec un type différent de "SUBMIT" la déclaration
ne devra pas être autorisée
"""
declaration_15 = AwaitingInstructionDeclarationFactory(overriden_article=Declaration.Article.ARTICLE_15)

# Double soumission
TestAutomaticApproval._create_submission_snapshot(declaration_15)
TestAutomaticApproval._create_submission_snapshot(declaration_15)

SnapshotFactory(
action=Snapshot.SnapshotActions.TAKE_FOR_INSTRUCTION,
status=Declaration.DeclarationStatus.AWAITING_INSTRUCTION,
declaration=declaration_15,
)

approve_declarations()
declaration_15.refresh_from_db()

self.assertEqual(declaration_15.status, Declaration.DeclarationStatus.AWAITING_INSTRUCTION)
latest_snapshot_15 = declaration_15.snapshots.latest("creation_date")
self.assertEqual(latest_snapshot_15.action, Snapshot.SnapshotActions.TAKE_FOR_INSTRUCTION)

def test_email_sent_declaration_approved(self, mocked_brevo):
"""
L'email d'approbation doit être envoyé lors d'une approbation automatique
Expand Down

0 comments on commit d6cfc45

Please sign in to comment.