Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Dépôt de besoin] Conservation des données des dépôts abandonnés #938

Merged
merged 8 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion lemarche/tenders/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from lemarche.perimeters.admin import PerimeterRegionFilter
from lemarche.tenders import constants
from lemarche.tenders.forms import TenderAdminForm
from lemarche.tenders.models import PartnerShareTender, Tender, TenderQuestion
from lemarche.tenders.models import PartnerShareTender, Tender, TenderQuestion, TenderStepsData
from lemarche.utils.admin.admin_site import admin_site
from lemarche.utils.apis import api_hubspot
from lemarche.utils.fields import ChoiceArrayField, pretty_print_readonly_jsonfield
Expand Down Expand Up @@ -591,3 +591,32 @@ def logs_display(self, partnersharetender=None):
return "-"

logs_display.short_description = PartnerShareTender._meta.get_field("logs").verbose_name


@admin.register(TenderStepsData, site=admin_site)
class TenderStepsDataAdmin(admin.ModelAdmin):
list_display = ["created_at", "updated_at", "uuid"]

readonly_fields = [
SebastienReuiller marked this conversation as resolved.
Show resolved Hide resolved
"id",
"created_at",
"updated_at",
"uuid",
"steps_data_display",
]

def steps_data_display(self, tender_steps_data: TenderStepsData = None):
if tender_steps_data:
return pretty_print_readonly_jsonfield(tender_steps_data.steps_data)
return "-"

steps_data_display.short_description = "Données saisies dans les étapes"

def has_add_permission(self, request):
return False

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

def has_delete_permission(self, request, obj=None):
return False
43 changes: 43 additions & 0 deletions lemarche/tenders/migrations/0058_tenderstepsdata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Generated by Django 4.2.2 on 2023-10-09 13:35

import django.utils.timezone
from django.db import migrations, models
from django_extensions.db.fields import ShortUUIDField
from shortuuid import uuid


class Migration(migrations.Migration):
dependencies = [
("tenders", "0057_alter_tender_siae_transactioned"),
]

operations = [
migrations.CreateModel(
name="TenderStepsData",
fields=[
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
(
"uuid",
ShortUUIDField(
auto_created=True,
blank=True,
db_index=True,
default=uuid,
editable=False,
unique=True,
verbose_name="Identifiant UUID",
),
),
(
"created_at",
models.DateTimeField(default=django.utils.timezone.now, verbose_name="Date de création"),
),
("updated_at", models.DateTimeField(auto_now=True, verbose_name="Date de modification")),
("steps_data", models.JSONField(default=list, editable=False, verbose_name="Données des étapes")),
],
options={
"verbose_name": "Besoin d'achat - Données des étapes",
"verbose_name_plural": "Besoins d'achat - Données des étapes",
},
),
]
30 changes: 30 additions & 0 deletions lemarche/tenders/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from django.utils.functional import cached_property
from django.utils.text import slugify
from django_better_admin_arrayfield.models.fields import ArrayField
from django_extensions.db.fields import ShortUUIDField
from shortuuid import uuid

from lemarche.perimeters.models import Perimeter
from lemarche.siaes import constants as siae_constants
Expand Down Expand Up @@ -761,3 +763,31 @@ class Meta:
@cached_property
def perimeters_list_string(self) -> str:
return ", ".join(self.perimeters.values_list("name", flat=True))


class TenderStepsData(models.Model):
FIELDS_TO_REDACT = [
"contact-contact_email",
"contact-contact_phone",
"contact-contact_last_name",
"contact-contact_first_name",
]

created_at = models.DateTimeField(verbose_name="Date de création", default=timezone.now)
updated_at = models.DateTimeField(verbose_name="Date de modification", auto_now=True)
uuid = ShortUUIDField(
verbose_name="Identifiant UUID",
default=uuid,
editable=False,
unique=True,
db_index=True,
auto_created=True,
)
steps_data = models.JSONField(verbose_name="Données des étapes", editable=False, default=list)

class Meta:
verbose_name = "Besoin d'achat - Données des étapes"
verbose_name_plural = "Besoins d'achat - Données des étapes"

def __str__(self):
return f"{self.uuid} - {self.created_at}"
7 changes: 6 additions & 1 deletion lemarche/www/pages/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from lemarche.sectors.models import Sector
from lemarche.siaes.models import Siae, SiaeGroup
from lemarche.tenders import constants as tender_constants
from lemarche.tenders.models import Tender
from lemarche.tenders.models import Tender, TenderStepsData
from lemarche.users.models import User
from lemarche.utils.tracker import track
from lemarche.www.pages.forms import (
Expand Down Expand Up @@ -357,6 +357,11 @@ def csrf_failure(request, reason=""): # noqa C901
tender.save()
tender.set_siae_found_list()

# remove steps data
uuid = request.session.get("tender_steps_data_uuid", None)
if uuid:
TenderStepsData.objects.filter(uuid=uuid).delete()

if settings.BITOUBI_ENV == "prod":
notify_admin_tender_created(tender)

Expand Down
11 changes: 10 additions & 1 deletion lemarche/www/tenders/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from lemarche.siaes.models import Siae
from lemarche.tenders import constants as tender_constants
from lemarche.tenders.factories import TenderFactory, TenderQuestionFactory
from lemarche.tenders.models import Tender, TenderSiae
from lemarche.tenders.models import Tender, TenderSiae, TenderStepsData
from lemarche.users.factories import UserFactory
from lemarche.users.models import User
from lemarche.www.tenders.views import TenderCreateMultiStepView
Expand Down Expand Up @@ -83,12 +83,21 @@ def _check_every_step(self, tenders_step_data, final_redirect_page: str = revers
# make sure that after the create tender we are redirected to ??
self.assertEqual(response.status_code, 200)
self.assertRedirects(response, final_redirect_page)
# has the step datas been cleaned ?
self.assertEqual(TenderStepsData.objects.count(), 0)
return response
else:
self.assertEqual(response.status_code, 200)
current_errors = response.context_data["form"].errors
self.assertEquals(current_errors, {})

# Is the step data stored correctly ?
tender_step_data = TenderStepsData.objects.first()
self.assertEqual(
data_step["tender_create_multi_step_view-current_step"],
tender_step_data.steps_data[-1]["tender_create_multi_step_view-current_step"],
)

def test_anyone_can_access_create_tender(self):
# anonymous
url = reverse("tenders:create")
Expand Down
36 changes: 35 additions & 1 deletion lemarche/www/tenders/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from lemarche.siaes.models import Siae
from lemarche.tenders import constants as tender_constants
from lemarche.tenders.models import Tender, TenderSiae
from lemarche.tenders.models import Tender, TenderSiae, TenderStepsData
from lemarche.users.models import User
from lemarche.utils.data import get_choice
from lemarche.utils.mixins import (
Expand Down Expand Up @@ -148,6 +148,35 @@ def get_context_data(self, form, **kwargs):
context.update({"tender": tender_dict})
return context

def process_step(self, form):
SebastienReuiller marked this conversation as resolved.
Show resolved Hide resolved
"""
Save step data
"""
data = form.data.copy()
SebastienReuiller marked this conversation as resolved.
Show resolved Hide resolved
if "csrfmiddlewaretoken" in data:
del data["csrfmiddlewaretoken"]

# Hide personal data
for field_to_redacted in TenderStepsData.FIELDS_TO_REDACT:
if field_to_redacted in data:
data[field_to_redacted] = "[REDACTED]"

data["timestamp"] = timezone.now().isoformat()

uuid = self.request.session.get("tender_steps_data_uuid", None)
if uuid:
try:
tender_steps_data = TenderStepsData.objects.get(uuid=uuid)
tender_steps_data.steps_data.append(data)
tender_steps_data.save()
except TenderStepsData.DoesNotExist:
tender_steps_data = TenderStepsData.objects.create(uuid=uuid, steps_data=[data])
else:
tender_steps_data = TenderStepsData.objects.create(steps_data=[data])
self.request.session["tender_steps_data_uuid"] = tender_steps_data.uuid

return form.data

def save_instance_tender(self, tender_dict: dict, form_dict: dict, is_draft: bool):
tender_status = tender_constants.STATUS_DRAFT if is_draft else tender_constants.STATUS_PUBLISHED
tender_published_at = None if is_draft else timezone.now()
Expand Down Expand Up @@ -201,6 +230,11 @@ def done(self, _, form_dict, **kwargs):
self.save_instance_tender(tender_dict=tender_dict, form_dict=form_dict, is_draft=is_draft)
self.instance.set_siae_found_list()

# remove steps data
uuid = self.request.session.get("tender_steps_data_uuid", None)
SebastienReuiller marked this conversation as resolved.
Show resolved Hide resolved
if uuid:
TenderStepsData.objects.filter(uuid=uuid).delete()

# we notify the admin team
if settings.BITOUBI_ENV == "prod":
notify_admin_tender_created(self.instance)
Expand Down