Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
rsebille committed Jan 2, 2025
1 parent 9076133 commit 922f8cf
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 60 deletions.
30 changes: 17 additions & 13 deletions itou/employee_record/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,6 @@ def company_data_sent(self, obj):
if not obj.archived_json:
return self.get_empty_value_display()

# Handle older data serialized from the JSON as string
if not isinstance(obj.archived_json, dict):
obj._set_archived_json(obj.archived_json)

siret = obj.archived_json["siret"]
measure = obj.archived_json["mesure"]
return f"{siret} ({measure})"
Expand All @@ -79,10 +75,6 @@ def user_data_sent(self, obj):
if not obj.archived_json:
return self.get_empty_value_display()

# Handle older data serialized from the JSON as string
if not isinstance(obj.archived_json, dict):
obj._set_archived_json(obj.archived_json)

firstname = obj.archived_json["personnePhysique"]["prenom"]
lastname = obj.archived_json["personnePhysique"]["nomUsage"]
id_itou = obj.archived_json["personnePhysique"]["idItou"]
Expand All @@ -93,16 +85,28 @@ def approval_data_sent(self, obj):
if not obj.archived_json:
return self.get_empty_value_display()

# Handle older data serialized from the JSON as string
if not isinstance(obj.archived_json, dict):
obj._set_archived_json(obj.archived_json)

number = obj.archived_json["personnePhysique"]["passIae"]
start = obj.archived_json["personnePhysique"]["passDateDeb"]
end = obj.archived_json["personnePhysique"]["passDateFin"]
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 +135,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
Expand Up @@ -3,7 +3,6 @@
from django.db import transaction
from django.utils import timezone
from rest_framework.parsers import JSONParser
from rest_framework.renderers import JSONRenderer
from sentry_sdk.crons import monitor

from itou.approvals.models import Approval
Expand Down Expand Up @@ -54,12 +53,11 @@ def _upload_batch_file(self, sftp: paramiko.SFTPClient, employee_records: list[E

# Now that file is transferred, update employee records status (SENT)
# and store in which file they have been sent
renderer = JSONRenderer()
for idx, employee_record in enumerate(employee_records, 1):
employee_record.sent(
file=remote_path,
line_number=idx,
archive=renderer.render(batch_data["lignesTelechargement"][idx - 1]),
archive=batch_data["lignesTelechargement"][idx - 1],
)

def _parse_feedback_file(self, feedback_file: str, batch: dict, dry_run: bool) -> None:
Expand Down Expand Up @@ -96,10 +94,9 @@ def _parse_feedback_file(self, feedback_file: str, batch: dict, dry_run: bool) -
self.stdout.write(f"Skipping, incoherent status for {employee_record=}")
continue

archived_json = JSONRenderer().render(raw_employee_record)
if processing_code == EmployeeRecord.ASP_PROCESSING_SUCCESS_CODE: # Processed by ASP
if not dry_run:
employee_record.process(code=processing_code, label=processing_label, archive=archived_json)
employee_record.process(code=processing_code, label=processing_label, archive=raw_employee_record)
else:
self.stdout.write(f"DRY-RUN: Accepted {employee_record=}, {processing_code=}, {processing_label=}")
else: # Rejected by ASP
Expand All @@ -108,7 +105,10 @@ def _parse_feedback_file(self, feedback_file: str, batch: dict, dry_run: bool) -
# 3436 processing code are automatically converted as PROCESSED
if processing_code == EmployeeRecord.ASP_DUPLICATE_ERROR_CODE:
employee_record.process(
code=processing_code, label=processing_label, archive=archived_json, as_duplicate=True
code=processing_code,
label=processing_label,
archive=raw_employee_record,
as_duplicate=True,
)

# If the ASP mark the employee record as duplicate,
Expand All @@ -129,7 +129,7 @@ def _parse_feedback_file(self, feedback_file: str, batch: dict, dry_run: bool) -

continue

employee_record.reject(code=processing_code, label=processing_label, archive=archived_json)
employee_record.reject(code=processing_code, label=processing_label, archive=raw_employee_record)
else:
self.stdout.write(f"DRY-RUN: Rejected {employee_record=}, {processing_code=}, {processing_label=}")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from django.conf import settings
from django.db import transaction
from rest_framework.parsers import JSONParser
from rest_framework.renderers import JSONRenderer
from sentry_sdk.crons import monitor

from itou.employee_record.common_management import EmployeeRecordTransferCommand, IgnoreFile
Expand Down Expand Up @@ -60,12 +59,11 @@ def _upload_batch_file(
self.stdout.write("DRY-RUN: Not *really* updating notification statuses")
return

renderer = JSONRenderer()
for idx, notification in enumerate(notifications, 1):
notification.sent(
file=remote_path,
line_number=idx,
archive=renderer.render(batch_data["lignesTelechargement"][idx - 1]),
archive=batch_data["lignesTelechargement"][idx - 1],
)

def _parse_feedback_file(self, feedback_file: str, batch: dict, dry_run: bool) -> None:
Expand Down Expand Up @@ -101,15 +99,14 @@ def _parse_feedback_file(self, feedback_file: str, batch: dict, dry_run: bool) -
self.stdout.write(f"Skipping, incoherent status for {notification=}")
continue

archived_json = JSONRenderer().render(employee_record)
if processing_code == EmployeeRecordUpdateNotification.ASP_PROCESSING_SUCCESS_CODE: # Processed by ASP
if not dry_run:
notification.process(code=processing_code, label=processing_label, archive=archived_json)
notification.process(code=processing_code, label=processing_label, archive=employee_record)
else:
self.stdout.write(f"DRY-RUN: Processed {notification}, {processing_code=}, {processing_label=}")
else: # Rejected by ASP
if not dry_run:
notification.reject(code=processing_code, label=processing_label, archive=archived_json)
notification.reject(code=processing_code, label=processing_label, archive=employee_record)
else:
self.stdout.write(f"DRY-RUN: Rejected {notification}: {processing_code=}, {processing_label=}")

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",
)
],
},
),
]
40 changes: 30 additions & 10 deletions itou/employee_record/models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import contextlib
import enum
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 @@ -78,21 +77,15 @@ class Meta:
]
ordering = ["-created_at"]

def _set_archived_json(self, archive):
if archive is not None:
with contextlib.suppress(json.JSONDecodeError):
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)
self.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)
self.archived_json = archive


class EmployeeRecordTransition(enum.StrEnum):
Expand Down Expand Up @@ -120,6 +113,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 @@ -453,6 +447,32 @@ 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
related_name="+",
)

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
2 changes: 1 addition & 1 deletion tests/api/employee_record_api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def test_fetch_employee_record_list(self, api_client, mocker, faker):
result = response.json()
assert len(result.get("results")) == 0

self.employee_record.process(code=process_code, label=process_message, archive="{}")
self.employee_record.process(code=process_code, label=process_message, archive={})
response = api_client.get(ENDPOINT_URL, format="json")
assert response.status_code == 200

Expand Down
Loading

0 comments on commit 922f8cf

Please sign in to comment.