Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
rsebille committed Dec 30, 2024
1 parent 4a1ca4a commit eb3a9b9
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 72 deletions.
18 changes: 17 additions & 1 deletion itou/employee_record/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,22 @@ def approval_data_sent(self, obj):
return f"{number} ({start}{end})"


class EmployeeRecordTransitionLog(ASPExchangeInformationAdminMixin, ReadonlyMixin, ItouTabularInline):
model = models.EmployeeRecordTransitionLog
extra = 0
fields = (
"transition",
"from_state",
"to_state",
"user",
"timestamp",
"asp_processing_code",
"asp_processing_label",
"asp_batch_file",
)
raw_id_fields = ("user",)


@admin.register(models.EmployeeRecord)
class EmployeeRecordAdmin(ASPExchangeInformationAdminMixin, ItouModelAdmin):
form = EmployeeRecordAdminForm
Expand Down Expand Up @@ -131,7 +147,7 @@ def schedule_approval_update_notification(self, request, queryset):
schedule_approval_update_notification,
]

inlines = (EmployeeRecordUpdateNotificationInline,)
inlines = (EmployeeRecordUpdateNotificationInline, EmployeeRecordTransitionLog)

list_display = (
"pk",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models

import itou.employee_record.models


class Migration(migrations.Migration):
dependencies = [
("employee_record", "0002_alter_employeerecord_status_and_more"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name="EmployeeRecordTransitionLog",
fields=[
("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("transition", models.CharField(db_index=True, max_length=255, verbose_name="transition")),
("from_state", models.CharField(db_index=True, max_length=255, verbose_name="from state")),
("to_state", models.CharField(db_index=True, max_length=255, verbose_name="to state")),
(
"timestamp",
models.DateTimeField(
db_index=True, default=django.utils.timezone.now, verbose_name="performed at"
),
),
(
"asp_processing_code",
models.CharField(max_length=4, null=True, verbose_name="code de traitement ASP"),
),
(
"asp_processing_label",
models.CharField(max_length=200, null=True, verbose_name="libellé de traitement ASP"),
),
(
"asp_batch_file",
models.CharField(
max_length=27,
null=True,
validators=[itou.employee_record.models.validate_asp_batch_filename],
verbose_name="fichier de batch ASP",
),
),
(
"asp_batch_line_number",
models.IntegerField(null=True, verbose_name="ligne correspondante dans le fichier batch ASP"),
),
(
"archived_json",
models.JSONField(blank=True, null=True, verbose_name="archive JSON de la fiche salarié"),
),
(
"employee_record",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="logs",
to="employee_record.employeerecord",
),
),
(
"user",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.RESTRICT,
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"verbose_name": "log des transitions de la fiche salarié",
"verbose_name_plural": "log des transitions des fiches salarié",
"ordering": ["-timestamp"],
"abstract": False,
"constraints": [
models.UniqueConstraint(
condition=models.Q(("asp_batch_file__isnull", False)),
fields=("asp_batch_file", "asp_batch_line_number"),
name="unique_employeerecordtransitionlog_asp_batch_file_and_line",
)
],
},
),
]
54 changes: 27 additions & 27 deletions itou/employee_record/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import json

from dateutil.relativedelta import relativedelta
from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from django.db.models import Exists, OuterRef
Expand Down Expand Up @@ -84,16 +85,6 @@ def _set_archived_json(self, archive):
archive = json.loads(archive)
self.archived_json = archive

def set_asp_batch_information(self, file, line_number, archive):
self.asp_batch_file = file
self.asp_batch_line_number = line_number
self._set_archived_json(archive)

def set_asp_processing_information(self, code, label, archive):
self.asp_processing_code = code
self.asp_processing_label = label
self._set_archived_json(archive)


class EmployeeRecordTransition(enum.StrEnum):
READY = "ready"
Expand All @@ -120,6 +111,7 @@ class EmployeeRecordWorkflow(xwf_models.Workflow):
(EmployeeRecordTransition.ENABLE, Status.DISABLED, Status.NEW),
(EmployeeRecordTransition.ARCHIVE, CAN_BE_ARCHIVED_STATES, Status.ARCHIVED),
)
log_model = "employee_record.EmployeeRecordTransitionLog"


class EmployeeRecordQuerySet(models.QuerySet):
Expand Down Expand Up @@ -317,15 +309,13 @@ def sent(self, *, file, line_number, archive):
The file name is stored for further feedback processing (also done via a file)
"""
self.clean()
self.set_asp_batch_information(file, line_number, archive)

@xwf_models.transition()
def reject(self, *, code, label, archive):
"""
Update status after an ASP rejection of the employee record
"""
self.clean()
self.set_asp_processing_information(code, label, archive)

@xwf_models.transition()
def process(self, *, code, label, archive, as_duplicate=False):
Expand All @@ -335,9 +325,6 @@ def process(self, *, code, label, archive, as_duplicate=False):
self.clean()
self.processed_at = timezone.now()
self.processed_as_duplicate = as_duplicate
self.set_asp_processing_information(
code, label if not as_duplicate else "Statut forcé suite à doublon ASP", archive
)

@xwf_models.transition()
def enable(self):
Expand Down Expand Up @@ -453,6 +440,31 @@ def from_job_application(cls, job_application, clean=True):
return fs


class EmployeeRecordTransitionLog(xwf_models.BaseTransitionLog, ASPExchangeInformation):
MODIFIED_OBJECT_FIELD = "employee_record"
EXTRA_LOG_ATTRIBUTES = (
("user", "user", None),
("asp_batch_file", "file", None),
("asp_batch_line_number", "line_number", None),
("asp_processing_code", "code", None),
("asp_processing_label", "label", None),
("archived_json", "archive", None),
)

employee_record = models.ForeignKey(EmployeeRecord, related_name="logs", on_delete=models.CASCADE)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
blank=True,
null=True,
on_delete=models.RESTRICT, # For traceability and accountability
)

class Meta(ASPExchangeInformation.Meta):
verbose_name = "log des transitions de la fiche salarié"
verbose_name_plural = "log des transitions des fiches salarié"
ordering = ["-timestamp"]


class EmployeeRecordBatch:
"""
Transient wrapper for a list of employee records.
Expand Down Expand Up @@ -583,15 +595,3 @@ class Meta(ASPExchangeInformation.Meta):

def __repr__(self):
return f"<{type(self).__name__} pk={self.pk}>"

@xwf_models.transition()
def sent(self, *, file, line_number, archive):
self.set_asp_batch_information(file, line_number, archive)

@xwf_models.transition()
def reject(self, *, code, label, archive):
self.set_asp_processing_information(code, label, archive)

@xwf_models.transition()
def process(self, *, code, label, archive):
self.set_asp_processing_information(code, label, archive)
44 changes: 0 additions & 44 deletions tests/employee_record/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from tests.companies.factories import CompanyFactory
from tests.employee_record.factories import (
BareEmployeeRecordFactory,
BareEmployeeRecordUpdateNotificationFactory,
EmployeeRecordFactory,
EmployeeRecordWithProfileFactory,
)
Expand Down Expand Up @@ -621,46 +620,3 @@ def test_for_asp_company(self):
EmployeeRecord.objects.for_asp_company(employee_record_2.job_application.to_company).get()
== employee_record_2
)


@pytest.mark.parametrize("factory", [BareEmployeeRecordFactory, BareEmployeeRecordUpdateNotificationFactory])
@pytest.mark.parametrize(
"archive,expected_archive",
[
('{"Hello": "World"}', {"Hello": "World"}),
("{}", {}),
("", ""),
(None, None),
],
ids=repr,
)
class TestASPExchangeInformationModel:
def test_set_asp_batch_information(self, factory, archive, expected_archive):
obj = factory()

obj.set_asp_batch_information("RIAE_FS_20230123103950.json", 42, archive)
obj.save()
obj.refresh_from_db()

assert obj.asp_batch_file == "RIAE_FS_20230123103950.json"
assert obj.asp_batch_line_number == 42
assert obj.archived_json == expected_archive

@pytest.mark.parametrize(
"code,expected_code",
[
("0000", "0000"),
(9999, "9999"),
],
ids=repr,
)
def test_set_asp_processing_information(self, factory, archive, expected_archive, code, expected_code):
obj = factory()

obj.set_asp_processing_information(code, "The label", archive)
obj.save()
obj.refresh_from_db()

assert obj.asp_processing_code == expected_code
assert obj.asp_processing_label == "The label"
assert obj.archived_json == expected_archive

0 comments on commit eb3a9b9

Please sign in to comment.