Skip to content
Snippets Groups Projects
Commit 8f272c38 authored by Michel Jouvin's avatar Michel Jouvin
Browse files

Merge branch 'export_multiple_contract' into 'master'

export: handle multiple contracts

See merge request hito/ositah!4
parents 988dd338 b9bb759a
No related branches found
No related tags found
No related merge requests found
......@@ -400,7 +400,7 @@ def analysis_layout():
return html.Div(
[
html.H1("Analyse et export des déclarations"),
html.H1("Analyse des déclarations"),
team_list_dropdown(),
# The following dcc.Store is used to ensure that the the ijclab_export input exists
# before the export page is created
......
......@@ -61,6 +61,12 @@ EXPORT_NSIP_SYNC_INDICATOR_ID = "export-nsip-sync-indicator"
EXPORT_NSIP_SAVED_SYNC_INDICATOR_ID = "export-nsip-saved-sync-indicator"
EXPORT_NSIP_SYNC_FREQUENCY = 2.0 # Average number of sync operations per second
EXPORT_NSIP_SYNC_TRIGGER_INTERVAL_ID = "export-nsip-sync-callback-interval"
EXPORT_NSIP_MULTIPLE_CONTRACTS_ERROR = re.compile(
(
r'"Agent has active multi-contracts in same laboratory - manual action needed\s+'
r"\|\s+idAgentContract\s+:\s+(?P<id1>\d+)\s+\|\s+idAgentContract\s+:\s+(?P<id2>\d+)"
)
)
NSIP_DECLARATIONS_SELECT_ALL = 0
NSIP_DECLARATIONS_SELECT_UNSYNCHRONIZED = 1
......@@ -1008,17 +1014,47 @@ def nsip_export_button(n_clicks, sync_indicator, previous_sync_indicator):
if n_clicks and n_clicks >= 1:
if sync_indicator > previous_sync_indicator:
for row in selected_declarations.itertuples(index=False):
# nsip_project_id and nsip_reference_id are NaN if undefined and a NaN value is
# not equal to itself!
project_type = row.nsip_project_id == row.nsip_project_id
activity_id = row.nsip_project_id if project_type else row.nsip_reference_id
(status, http_status, http_reason,) = global_params.nsip.update_declaration(
row.email_reseda,
activity_id,
project_type,
row.time,
row.validation_time,
)
# One of the possible error during declaration update is that the user has
# multiple contracts attached to the lab for the current period. In this case
# the update is retried with the second contract (generally the current one)
# mentioned in the error message.
retry_on_error = True
retry_attempts = 0
contract = None
while retry_on_error:
# nsip_project_id and nsip_reference_id are NaN if undefined and a NaN value is
# not equal to itself!
project_type = row.nsip_project_id == row.nsip_project_id
activity_id = row.nsip_project_id if project_type else row.nsip_reference_id
(
status,
http_status,
http_reason,
) = global_params.nsip.update_declaration(
row.email_reseda,
activity_id,
project_type,
row.time,
row.validation_time,
contract,
)
if status > 0 and http_status:
m = EXPORT_NSIP_MULTIPLE_CONTRACTS_ERROR.match(http_reason)
# Never retry more than once
if m and (retry_attempts == 0):
contract = m.group("id2")
retry_attempts += 1
print(
(
f"Agent {row.email_reseda} has several contracts for the"
f" current period: retrying update with contract {contract}"
)
)
else:
retry_on_error = False
else:
retry_on_error = False
if status <= 0:
# Log a message if the declaration was successfully added to NSIP to make
......
# Module with utility functions
# Singleton decorator definition
def singleton(cls):
instances = {}
......
......@@ -66,7 +66,6 @@ project_teams = db.Table(
class Agent(db.Model):
id = db.Column(db.String, primary_key=True)
nom = db.Column(db.String)
prenom = db.Column(db.String)
......@@ -96,7 +95,6 @@ class Agent(db.Model):
class Carriere(db.Model):
id = db.Column(db.String, primary_key=True)
date_debut = db.Column(db.DateTime)
date_fin = db.Column(db.DateTime)
......@@ -113,7 +111,6 @@ class Carriere(db.Model):
class Team(db.Model):
id = db.Column(db.String, primary_key=True)
nom = db.Column(db.String)
description = db.Column(db.String)
......@@ -128,7 +125,6 @@ class Team(db.Model):
class Referentiel(db.Model):
id = db.Column(db.Integer, primary_key=True)
libelle = db.Column(db.String)
ordre = db.Column(db.Integer)
......@@ -139,7 +135,6 @@ class Referentiel(db.Model):
class Activite(db.Model):
id = db.Column(db.String, primary_key=True, default=new_uuid)
libelle = db.Column(db.String)
description = db.Column(db.String)
......@@ -172,7 +167,6 @@ class Activite(db.Model):
class Projet(db.Model):
id = db.Column(db.String, primary_key=True, default=new_uuid)
libelle = db.Column(db.String)
description = db.Column(db.String)
......@@ -205,7 +199,6 @@ class Projet(db.Model):
class ActiviteDetail(db.Model):
id = db.Column(db.Integer, primary_key=True)
activite_id = db.Column(db.String, db.ForeignKey("activite.id"))
projet_id = db.Column(db.String, db.ForeignKey("projet.id"))
......@@ -234,14 +227,12 @@ class ActiviteDetail(db.Model):
class OSITAHSession(db.Model):
id = db.Column(db.String(36), primary_key=True)
email = db.Column(db.String(255), nullable=False)
last_use = db.Column(db.DateTime, nullable=False)
class OSITAHValidation(db.Model):
id = db.Column(db.String(36), primary_key=True, default=new_uuid)
validated = db.Column(db.Boolean, nullable=False)
timestamp = db.Column(db.DateTime, nullable=False)
......@@ -258,7 +249,6 @@ class OSITAHValidation(db.Model):
class OSITAHValidationPeriod(db.Model):
id = db.Column(db.String(36), primary_key=True, default=new_uuid)
name = db.Column(db.String(255), unique=True, nullable=False)
start_date = db.Column(db.DateTime, nullable=False)
......@@ -267,7 +257,6 @@ class OSITAHValidationPeriod(db.Model):
class OSITAHProjectDeclaration(db.Model):
id = db.Column(db.String(36), primary_key=True, default=new_uuid)
projet = db.Column(db.String(255), nullable=False)
masterprojet = db.Column(db.String(255), nullable=False)
......
......@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "ositah"
version = "22.11"
version = "23.2"
description = "Outils de Suivi d'Activités basé sur Hito"
readme = "README.md"
requires-python = ">=3.8"
......@@ -21,7 +21,7 @@ dependencies = [
"flask-multipass",
"flask-sqlalchemy<3",
"flask-wtf",
"hito-tools",
"hito-tools>=23.2",
"pandas",
"pymysql",
"python-ldap",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment