Contrainte champ obligatoire sur un multi-Doc

Problem description

Bonjour,
Nous essayons de rendre obligatoire un champ de type multidoc lors d’une transition d’état

Steps to reproduce

Nous avons testé deux solutions :
A. Par le code
En utilisant le hook pre-update, et en vérifiant la condition suivante :

if ((getOldStatus().equals("INIT") && getStatus().equals("COMPLETED")) ||(getOldStatus().equals("LACK_INFOS") && getStatus().equals("COMPLETED")) ){
			//si au moins un doc n'est pas chargé, alerte
                        //vérification de ce que ressort la méthode "getDocuments"
			AppLog.info("===================doc="+	getField("evlValReporting").getDocuments(this, getRowId()), Grant.getSystemAdmin());
			if(getField("evlValReporting").getDocuments(this, getRowId())==null ) {
				 return Message.formatError("EVL_ERROR_COMPLETION", "Merci de compléter le Compte de résultat.", "evlValReporting");

La partie AppLog.info ressort ceci, bien qu’un doc a été chargé. La contrainte par le “if” n’est donc pas appliquée

===================doc={"size":0,"contenttype":""}

B. Par les contraintes

  1. Nous avons créé une contrainte BackEnd

  2. Lorsqu’on teste la contrainte elle fonctionne, seulement le message d’erreur est le suivant :

On perd la fonctionnalité qui nous indique quel champ nécessite d’être renseigné + son emplacement.

Nous avons fait le test pour un doc simple, cela fonctionne parfaitement.

On détecte donc deux problématiques sur l’utilisation des multidoc :

  1. La méthode getDocuments ne retournent rien, même si au moins un document est renseigné. Elle n’est donc pas exploitable. D’ailleurs cette méthode n’est pas dans la javadoc, bien qu’elle apparaisse ici : Doc simplicité

  2. L’utilisation des contraintes sur des champs multidoc ne reproduit pas le même comportement que pour des champ “simple” document.

Technical information

Instance /health
[Platform]
Status=OK
Version=5.2.2
BuiltOn=2022-04-29 15:38
Git=5.2/a2c69b2ee78658770a248e617730e607252990ca
Encoding=UTF-8
EndpointIP=10.201.58.66
EndpointURL=http://siparex-simplicite-dev-777bcd4cfc-dqxdr:8080
TimeZone=Europe/Paris
SystemDate=2022-05-13 12:00:17
Simplicité logs
> `===================doc={"size":0,"contenttype":""}`
Browser logs
RAS
Other relevant information

RAS

Bonjour Ophélie,

1) Par le code

Voici la correction, il y a une erreur dans votre approche, mais c’est compréhensible, l’API n’étant pas très sympathique dans ce contexte.

	@Override
	public String preUpdate() {
		if (!getOldStatus().equals(getStatus())){
			// la bonne façon de compter le nombre de docs
			int countDocs = getField("demoOrdMultiDoc").getDocuments(this, getRowId()).getDocuments().size();
			// quelques explications sur votre ligne de log plus bas (*) 
			AppLog.info("===================docs="+	getField("demoOrdMultiDoc").getDocuments(this, getRowId()), getGrant());
			
			if(countDocs==0) {
				 return Message.formatError("ERROR_MULTIDOC", "Merci de compléter le multi-doc.", "demoOrdMultiDoc");
			}
		}
		return null;
	}

Concernant votre ligne de log:

  1. getDocuments renvoie un type com.simplicite.util.DocumentDB
  2. ici, ça revient à appeler DocumentDB.toString() qui renvoie {size:0,contenttype:} où size est la taille du document et contentype son type. Pour un multiDoc, la réponse devrait plut être un array du genre [{size:32546,contenttype:image/jpeg}]|
  3. dans le cas d’un multiDoc, il faut utiliser https://docs.simplicite.io/5/javadoc/com/simplicite/util/DocumentDB.html#getDocuments() qui renvoie la LISTE des documents
  4. je conviens qu’il est confusant que ObjectField.getDocuments ne renvoie pas directement une liste de DocumentDB et que DocumentDB fasse double-emploi pour du single et du multi-doc, l’API laisse un peu à désirer sur ce point. A minima elle devrait remonter des exceptions si on utilise des méthode single-doc sur un DocumentDB multiDoc… (cc @Francois )

2) Par contrainte

Reproduit:

Single

Simplicité®

Multi

Simplicité®

Proposition

  1. @Francois
    • implémenter des exceptions et clarifications sur l’API multi-doc
    • ajouter le msg d’erreur de contrainte au niveau du field
  2. @OphelieG
    • en contournement du problème sur la contrainte, utilisez la correction donnée pour le code
  • field.getDocuments n’est pas un accesseur à une liste de documents mais au document chapeau qui les regroupe tous. Il aurait fallu l’appeler loadDocuments car ça charge la définition des documents et retourne le document chapeau.
  • oui field.toString() n’est pas très malin, et devrait retourner une liste

Pour rendre obligatoire un document, il suffit juste de mettre une cardinalité dans le Document/Bookshelf associé au champ, tout comme les mime-types autorisés :

Pas besoin de contrainte ou de code.

@OphelieG

Expliqué dans ma réponse ci-dessus, et démontré dans l’exemple de code.

Cf la problématique énoncée qui est de rendre obligatoire sur certaines transitions d’états uniquement, d’où le besoin de contrainte ou de code.


Je t’ai plutôt taggé pour les problématiques suivantes :upside_down_face:

  • certaines méthodes de l’API DocumentDB n’ont pas de sens selon que ce soit un document chapeau ou pas
    • soit elles doivent être adaptées (exemple de toString)
    • soit elles doivent renvoyer une exception (valable dans les deux sens, DocumentDB.getDocuments() n’a pas de sens si c’est pas un document chapeau)
  • la contrainte sur mutli-doc obligatoire n’affiche pas l’erreur au niveau du field

Non car elles retournent déjà null si c’est pas le bon type. Le code peut déjà tester si c’est non null, pas un try/catch…
On peut cependant ajouter un warning explicite dans les logs. Ce n’a pas à être une exception au sens java (trop d’impact / breaking change peu utile = il faut refactorer tous les appels, non compatibilité ascendante du code spécifique… à éviter).

Ca oui, on va améliorer la java doc et le toString qui est confusant dans ce cas.

Jamais implémenté, on va l’ajouter ça doit pas être méchant à faire en front et back.

Ok j’avais pas cette info, dans ce cas petite une question fonctionnelle : si 1 des documents est obligatoire à une certaine étape, pourquoi ne pas modéliser :

  • un champ Document unique “principal”, comme un contrat (forcement PDF et qui devient obligatoire à un certain moment)
  • et les autres dans un champ documents multiples et optionnels : les documents annexes ou PJ sans controle

Là si on insère 10 documents, je vois pas très bien lequel était obligatoire parmi les 10, si ça se trouve l’utilisateur n’a pas renseigné le contrat, juste des annexes. Le test > 0 n’est pas vraiment métier. Généralement on met les champs obligatoires/engageants à part pour ne pas les mélanger avec des données optionnelles.

Les changements ont été faits et seront poussés au prochain build 5.2.4

  • Fixed: required multi-doc message displayed on field
  • New methods:
    • ObjectField.loadDocuments : confusing ObjectField.getDocuments is deprecated and replaced by loadDocuments
    • ObjectField.getListOfDocuments : return a list of documents if field is multi-doc (or null)

et le toString d’un document multiple retournera un tableau JSON.