forked from ScoDoc/ScoDoc
API: enrichit création/édition GroupDescr
This commit is contained in:
parent
e41879a1e1
commit
ea1a03a654
@ -303,15 +303,19 @@ def group_create(partition_id: int): # partition-group-create
|
|||||||
return json_error(403, "partition non editable")
|
return json_error(403, "partition non editable")
|
||||||
if not partition.formsemestre.can_change_groups():
|
if not partition.formsemestre.can_change_groups():
|
||||||
return json_error(401, "opération non autorisée")
|
return json_error(401, "opération non autorisée")
|
||||||
data = request.get_json(force=True) # may raise 400 Bad Request
|
|
||||||
group_name = data.get("group_name")
|
|
||||||
if group_name is None:
|
|
||||||
return json_error(API_CLIENT_ERROR, "missing group name or invalid data format")
|
|
||||||
if not GroupDescr.check_name(partition, group_name):
|
|
||||||
return json_error(API_CLIENT_ERROR, "invalid group_name")
|
|
||||||
group_name = group_name.strip()
|
|
||||||
|
|
||||||
group = GroupDescr(group_name=group_name, partition_id=partition_id)
|
args = request.get_json(force=True) # may raise 400 Bad Request
|
||||||
|
group_name = args.get("group_name")
|
||||||
|
if not isinstance(group_name, str):
|
||||||
|
return json_error(API_CLIENT_ERROR, "missing group name or invalid data format")
|
||||||
|
args["group_name"] = args["group_name"].strip()
|
||||||
|
if not GroupDescr.check_name(partition, args["group_name"]):
|
||||||
|
return json_error(API_CLIENT_ERROR, "invalid group_name")
|
||||||
|
args["partition_id"] = partition_id
|
||||||
|
try:
|
||||||
|
group = GroupDescr(**args)
|
||||||
|
except TypeError:
|
||||||
|
return json_error(API_CLIENT_ERROR, "invalid arguments")
|
||||||
db.session.add(group)
|
db.session.add(group)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
log(f"created group {group}")
|
log(f"created group {group}")
|
||||||
@ -369,16 +373,22 @@ def group_edit(group_id: int):
|
|||||||
return json_error(403, "partition non editable")
|
return json_error(403, "partition non editable")
|
||||||
if not group.partition.formsemestre.can_change_groups():
|
if not group.partition.formsemestre.can_change_groups():
|
||||||
return json_error(401, "opération non autorisée")
|
return json_error(401, "opération non autorisée")
|
||||||
data = request.get_json(force=True) # may raise 400 Bad Request
|
|
||||||
group_name = data.get("group_name")
|
args = request.get_json(force=True) # may raise 400 Bad Request
|
||||||
if group_name is not None:
|
if "group_name" in args:
|
||||||
group_name = group_name.strip()
|
if not isinstance(args["group_name"], str):
|
||||||
if not GroupDescr.check_name(group.partition, group_name, existing=True):
|
return json_error(API_CLIENT_ERROR, "invalid data format for group_name")
|
||||||
|
args["group_name"] = args["group_name"].strip() if args["group_name"] else ""
|
||||||
|
if not GroupDescr.check_name(
|
||||||
|
group.partition, args["group_name"], existing=True
|
||||||
|
):
|
||||||
return json_error(API_CLIENT_ERROR, "invalid group_name")
|
return json_error(API_CLIENT_ERROR, "invalid group_name")
|
||||||
group.group_name = group_name
|
|
||||||
db.session.add(group)
|
group.from_dict(args)
|
||||||
db.session.commit()
|
db.session.add(group)
|
||||||
log(f"modified {group}")
|
db.session.commit()
|
||||||
|
log(f"modified {group}")
|
||||||
|
|
||||||
app.set_sco_dept(group.partition.formsemestre.departement.acronym)
|
app.set_sco_dept(group.partition.formsemestre.departement.acronym)
|
||||||
sco_cache.invalidate_formsemestre(group.partition.formsemestre_id)
|
sco_cache.invalidate_formsemestre(group.partition.formsemestre_id)
|
||||||
return group.to_dict(with_partition=True)
|
return group.to_dict(with_partition=True)
|
||||||
|
@ -53,8 +53,9 @@ class ScoDocModel:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def filter_model_attributes(cls, data: dict, excluded: set[str] = None) -> dict:
|
def filter_model_attributes(cls, data: dict, excluded: set[str] = None) -> dict:
|
||||||
"""Returns a copy of dict with only the keys belonging to the Model and not in excluded.
|
"""Returns a copy of dict with only the keys belonging to the Model and not in excluded.
|
||||||
By default, excluded == { 'id' }"""
|
Add 'id' to excluded."""
|
||||||
excluded = {"id"} if excluded is None else set()
|
excluded = excluded or set()
|
||||||
|
excluded.add("id") # always exclude id
|
||||||
# Les attributs du modèle qui sont des variables: (élimine les __ et les alias comme adm_id)
|
# Les attributs du modèle qui sont des variables: (élimine les __ et les alias comme adm_id)
|
||||||
my_attributes = [
|
my_attributes = [
|
||||||
a
|
a
|
||||||
|
@ -11,14 +11,14 @@ from operator import attrgetter
|
|||||||
from sqlalchemy.exc import IntegrityError
|
from sqlalchemy.exc import IntegrityError
|
||||||
|
|
||||||
from app import db, log
|
from app import db, log
|
||||||
from app.models import Scolog, GROUPNAME_STR_LEN, SHORT_STR_LEN
|
from app.models import ScoDocModel, Scolog, GROUPNAME_STR_LEN, SHORT_STR_LEN
|
||||||
from app.models.etudiants import Identite
|
from app.models.etudiants import Identite
|
||||||
from app.scodoc import sco_cache
|
from app.scodoc import sco_cache
|
||||||
from app.scodoc import sco_utils as scu
|
from app.scodoc import sco_utils as scu
|
||||||
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
|
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
|
||||||
|
|
||||||
|
|
||||||
class Partition(db.Model):
|
class Partition(db.Model, ScoDocModel):
|
||||||
"""Partition: découpage d'une promotion en groupes"""
|
"""Partition: découpage d'une promotion en groupes"""
|
||||||
|
|
||||||
__table_args__ = (db.UniqueConstraint("formsemestre_id", "partition_name"),)
|
__table_args__ = (db.UniqueConstraint("formsemestre_id", "partition_name"),)
|
||||||
@ -204,7 +204,7 @@ class Partition(db.Model):
|
|||||||
return group
|
return group
|
||||||
|
|
||||||
|
|
||||||
class GroupDescr(db.Model):
|
class GroupDescr(db.Model, ScoDocModel):
|
||||||
"""Description d'un groupe d'une partition"""
|
"""Description d'un groupe d'une partition"""
|
||||||
|
|
||||||
__tablename__ = "group_descr"
|
__tablename__ = "group_descr"
|
||||||
|
@ -617,7 +617,7 @@
|
|||||||
listeGroupesAutoaffectation();
|
listeGroupesAutoaffectation();
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données.</h2>";
|
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (1).</h2>";
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,13 +665,13 @@
|
|||||||
document.querySelector(`#zoneGroupes .partition[data-idpartition="${idPartition}"]`).innerHTML += templateGroupe_zoneGroupes(r.id, name);
|
document.querySelector(`#zoneGroupes .partition[data-idpartition="${idPartition}"]`).innerHTML += templateGroupe_zoneGroupes(r.id, name);
|
||||||
|
|
||||||
// Lancement de l'édition du nom
|
// Lancement de l'édition du nom
|
||||||
divGroupe.querySelector(".modif").click();
|
// divGroupe.querySelector(".modif").click();
|
||||||
|
|
||||||
listeGroupesAutoaffectation();
|
listeGroupesAutoaffectation();
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données.</h2>";
|
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (4).</h2>";
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************/
|
/********************/
|
||||||
@ -746,12 +746,12 @@
|
|||||||
.then(r => { return r.json() })
|
.then(r => { return r.json() })
|
||||||
.then(r => {
|
.then(r => {
|
||||||
if (!r) {
|
if (!r) {
|
||||||
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données.</h2>";
|
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (2).</h2>";
|
||||||
}
|
}
|
||||||
listeGroupesAutoaffectation();
|
listeGroupesAutoaffectation();
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données.</h2>";
|
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (3).</h2>";
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -802,7 +802,7 @@
|
|||||||
.then(r => { return r.json() })
|
.then(r => { return r.json() })
|
||||||
.then(r => {
|
.then(r => {
|
||||||
if (r.OK != true) {
|
if (r.OK != true) {
|
||||||
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données.</h2>";
|
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (5).</h2>";
|
||||||
}
|
}
|
||||||
listeGroupesAutoaffectation();
|
listeGroupesAutoaffectation();
|
||||||
})
|
})
|
||||||
@ -916,12 +916,12 @@
|
|||||||
.then(r => { return r.json() })
|
.then(r => { return r.json() })
|
||||||
.then(r => {
|
.then(r => {
|
||||||
if (!r) {
|
if (!r) {
|
||||||
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données.</h2>";
|
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (6).</h2>";
|
||||||
}
|
}
|
||||||
listeGroupesAutoaffectation();
|
listeGroupesAutoaffectation();
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données.</h2>";
|
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (7).</h2>";
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
[pytest]
|
[pytest]
|
||||||
|
norecursedirs = .git app/static
|
||||||
markers =
|
markers =
|
||||||
slow: marks tests as slow (deselect with '-m "not slow"')
|
slow: marks tests as slow (deselect with '-m "not slow"')
|
||||||
apo
|
apo
|
||||||
|
@ -90,6 +90,7 @@ def test_formsemestre_partition(api_headers):
|
|||||||
)
|
)
|
||||||
assert isinstance(group_r, dict)
|
assert isinstance(group_r, dict)
|
||||||
assert group_r["group_name"] == group_d["group_name"]
|
assert group_r["group_name"] == group_d["group_name"]
|
||||||
|
assert group_r["edt_id"] is None
|
||||||
# --- Liste groupes de la partition
|
# --- Liste groupes de la partition
|
||||||
partition = GET(f"/partition/{partition_r['id']}", headers=headers)
|
partition = GET(f"/partition/{partition_r['id']}", headers=headers)
|
||||||
assert isinstance(partition, dict)
|
assert isinstance(partition, dict)
|
||||||
@ -99,6 +100,26 @@ def test_formsemestre_partition(api_headers):
|
|||||||
group = partition["groups"][str(group_r["id"])] # nb: str car clés json en string
|
group = partition["groups"][str(group_r["id"])] # nb: str car clés json en string
|
||||||
assert group["group_name"] == group_d["group_name"]
|
assert group["group_name"] == group_d["group_name"]
|
||||||
|
|
||||||
|
# --- Ajout d'un groupe avec edt_id
|
||||||
|
group_d = {"group_name": "extra", "edt_id": "GEDT"}
|
||||||
|
group_r = POST_JSON(
|
||||||
|
f"/partition/{partition_r['id']}/group/create",
|
||||||
|
group_d,
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
|
assert group_r["edt_id"] == "GEDT"
|
||||||
|
# Edit edt_id
|
||||||
|
group_r = POST_JSON(
|
||||||
|
f"/group/{group_r['id']}/edit",
|
||||||
|
{"edt_id": "GEDT2"},
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
|
assert group_r["edt_id"] == "GEDT2"
|
||||||
|
partition = GET(f"/partition/{partition_r['id']}", headers=headers)
|
||||||
|
group = partition["groups"][str(group_r["id"])] # nb: str car clés json en string
|
||||||
|
assert group["group_name"] == group_d["group_name"]
|
||||||
|
assert group["edt_id"] == "GEDT2"
|
||||||
|
|
||||||
# Place un étudiant dans le groupe
|
# Place un étudiant dans le groupe
|
||||||
etud = GET(f"/formsemestre/{formsemestre_id}/etudiants", headers=headers)[0]
|
etud = GET(f"/formsemestre/{formsemestre_id}/etudiants", headers=headers)[0]
|
||||||
repl = POST_JSON(f"/group/{group['id']}/set_etudiant/{etud['id']}", headers=headers)
|
repl = POST_JSON(f"/group/{group['id']}/set_etudiant/{etud['id']}", headers=headers)
|
||||||
|
Loading…
Reference in New Issue
Block a user