/trunk/services/modules/0.1/observations/ListeObservations2.php |
---|
481,6 → 481,10 |
'(vdi.mots_cles_texte IS NULL OR vdi.mots_cles_texte NOT LIKE "%aDeterminer%"', |
)) . ')'; |
} |
if(array_key_exists('validees', $val)) { |
//On récupère toutes les observations ayant un commentaire doté de proposition_retenue = 1 |
$req['join'][] = 'INNER JOIN del_commentaire AS dc ON vdi.id_observation = dc.ce_observation AND dc.proposition_retenue = 1'; |
} |
// solution n°1: impraticable |
if(false && array_key_exists('endiscussion', $val)) { |
704,10 → 708,10 |
$p['masque.tag'] = implode('|', array_filter($x)); |
} |
// masque.type: ['adeterminer', 'aconfirmer', 'endiscussion'] |
// masque.type: ['adeterminer', 'aconfirmer', 'endiscussion', 'validees'] |
if(isset($params['masque.type'])) { |
$p['masque.type'] = array_flip(array_intersect(array_filter(explode(';', $params['masque.type'])), |
array('adeterminer', 'aconfirmer', 'endiscussion'))); |
array('adeterminer', 'aconfirmer', 'endiscussion', 'validees'))); |
} |
/trunk/services/modules/0.1/determinations/ValiderDetermination.php |
---|
36,13 → 36,10 |
$this->verifierParametres($ressources, $parametres); |
$id_proposition = $ressources[1]; |
$retour = $this->modifierObservationParDetermination($id_proposition, $parametres); |
if ($retour == false) { |
if(!$this->modifierObservationParDetermination($id_proposition, $parametres)) |
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR); |
} else { |
RestServeur::envoyerEnteteStatutHttp(RestServeur::HTTP_CODE_OK); |
} |
RestServeur::envoyerEnteteStatutHttp(RestServeur::HTTP_CODE_OK); |
} |
public function verifierParametres($ressources, $parametres) { |
66,6 → 63,10 |
private function modifierObservationParDetermination($id_proposition, $parametres) { |
$informations_proposition = self::obtenirInformationDetermination($this->bdd, $id_proposition, $parametres['auteur.id']); |
if(! $informations_proposition) { |
throw new Exception("Cette proposition est invalide.", RestServeur::HTTP_CODE_ERREUR); |
} |
$id_observation = $informations_proposition['ce_observation']; |
// obtenirInformationsObservation() |
$informations_observation = $this->bdd->recuperer(sprintf('SELECT * FROM del_observation WHERE id_observation = %d', |
74,11 → 75,21 |
if(! $est_autorise) { |
throw new Exception("Seul l'utilisateur ayant saisi l'observation peut la valider : veuillez vous identifier.\n", |
RestServeur::HTTP_CODE_ERREUR); |
return; |
} |
$informations_proposition['ce_utilisateur'] = $informations_observation['ce_utilisateur']; |
return $this->envoyerRequeteModificationObservation($id_observation, $informations_proposition); |
$ret = $this->envoyerRequeteModificationObservation($id_observation, $informations_proposition); |
// cf cel/jrest/services/CelValidationObservation.php::updateElement() |
// TODO: check sur HTTP code == 200, plutôt que sur texte |
if($ret == 'ok' || $ret == 'OK') { |
// remet à 0 le status "proposition_retenue" pour toutes les propositions faites sur cette |
// observation à l'exception de celle désormais validée |
$this->bdd->requeter(sprintf('UPDATE del_commentaire SET proposition_retenue = IF(id_commentaire = %d, 1, 0)' . |
' WHERE ce_observation = %d -- %s', |
$informations_proposition['id_commentaire'], $id_observation, __FILE__ . ':' . __LINE__)); |
} |
return $ret; |
} |
private function comparerAuteurObservationUtilisateurIdentifie($ce_utilisateur) { |
/trunk/doc/bdd/schema_bdd_del.pdf |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/doc/bdd/sql/del.sql |
---|
100,7 → 100,7 |
`intitule` VARCHAR(255) NOT NULL , |
`descriptif` TEXT NULL , |
`tag` VARCHAR(255) NULL , |
`mots_cles` TEXT NULL COMMENT 'Mots clés associés au protocole, ceux ci déterminent les mots clés présentés \"à cocher\" dans l\'interface, lorsque le protocole est selectionné' , |
`mots_cles` VARCHAR(600) NOT NULL COMMENT 'Mots clés associés au protocole, ceux ci déterminent les mots clés présentés \"à cocher\" dans l\'interface, lorsque le protocole est selectionné' , |
PRIMARY KEY (`id_protocole`) ) |
ENGINE = MyISAM |
DEFAULT CHARACTER SET = utf8 |
156,8 → 156,8 |
CREATE TABLE IF NOT EXISTS `del_commentaire` ( |
`id_commentaire` BIGINT NOT NULL AUTO_INCREMENT , |
`ce_observation` BIGINT NOT NULL , |
`ce_proposition` INT NULL DEFAULT '0' , |
`ce_commentaire_parent` BIGINT NULL DEFAULT '0' , |
`ce_proposition` INT NULL DEFAULT 0 , |
`ce_commentaire_parent` BIGINT NULL DEFAULT 0 , |
`texte` TEXT NULL DEFAULT NULL , |
`ce_utilisateur` INT NULL DEFAULT '0' , |
`utilisateur_prenom` VARCHAR(255) NOT NULL , |
171,7 → 171,8 |
`famille` VARCHAR(255) NULL DEFAULT NULL , |
`nom_referentiel` VARCHAR(255) NULL DEFAULT NULL , |
`date` DATETIME NOT NULL COMMENT 'Date de création du commentaire.' , |
`proposition_initiale` INT(1) NOT NULL DEFAULT '0' , |
`proposition_initiale` INT(1) NOT NULL DEFAULT 0 COMMENT 'La proposition initiale est le nom_sel d\'origine copié ici dès lors que des commentaires adviennent.' , |
`proposition_retenue` INT(1) NOT NULL DEFAULT 0 COMMENT 'La proposition \"validée\" une fois que l\'auteur à validé et que le nom_sel de cel_obs a été modifié à partir du nom_sel de del_commentaire.' , |
PRIMARY KEY (`id_commentaire`) ) |
ENGINE = MyISAM |
DEFAULT CHARACTER SET = utf8 |
/trunk/doc/bdd/schema_bdd_del.mwb |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/scripts/modules/maj/201310-propret.sql |
---|
New file |
0,0 → 1,103 |
DELIMITER | |
-- initialisation (structure) |
DROP PROCEDURE IF EXISTS update_struct; |
CREATE PROCEDURE update_struct() |
BEGIN |
-- ajout de la colonne "proposition_retenue" |
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S21' SELECT "colonne proposition_retenue déjà existante"; /* = Duplicate column name */ |
ALTER TABLE `BASEDEL`.`del_commentaire` ADD `proposition_retenue` INT(1) NOT NULL DEFAULT 0 COMMENT "La proposition \"validée\" une fois que l'auteur à validé et que le nom_sel de cel_obs a été modifié à partir du nom_sel de del_commentaire."; -- ' |
END; |
| |
-- petite functon bonus |
DROP PROCEDURE IF EXISTS getCommentaires; |
CREATE PROCEDURE getCommentaires(IN _s1 INT(20)) |
BEGIN |
SELECT id_commentaire, ce_observation, ce_proposition, texte, nom_sel, nom_sel_nn, proposition_retenue FROM `BASEDEL`.`del_commentaire` WHERE ce_observation = _s1; |
END; |
| |
-- procédure créant des tables temporaires permettant de faciliter le processus de MAJ |
DROP PROCEDURE rebuild_retenues; |
CREATE PROCEDURE rebuild_retenues() |
BEGIN |
DROP TEMPORARY TABLE IF EXISTS _temp_having_retenue, _temp_multi_prop, _temp_mono_prop; |
-- les observations déjà retenues (pour pouvoir être exclues des processus postérieurs) |
CREATE TEMPORARY TABLE _temp_having_retenue ENGINE=MEMORY AS ( \ |
SELECT ce_observation FROM `BASEDEL`.`del_commentaire` co WHERE proposition_retenue = 1); |
-- observations ayant plusieurs propositions (= commentaire dont nom_sel IS NOT NULL) |
CREATE TEMPORARY TABLE IF NOT EXISTS _temp_multi_prop ENGINE=MEMORY AS ( \ |
SELECT ce_observation FROM `BASEDEL`.`del_commentaire` co \ |
WHERE nom_sel IS NOT NULL \ |
AND proposition_retenue = 0 /* == ce_observation NOT IN (SELECT ce_proposition FROM _temp_having_retenue) */ \ |
GROUP BY ce_observation HAVING COUNT(id_commentaire) > 1); -- 1053 |
-- observations ayant une seule proposition (= commentaire dont nom_sel IS NOT NULL) |
CREATE TEMPORARY TABLE IF NOT EXISTS _temp_mono_prop ENGINE=MEMORY AS ( \ |
SELECT ce_observation FROM `BASEDEL`.`del_commentaire` \ |
WHERE nom_sel IS NOT NULL \ |
AND proposition_retenue = 0 /* == ce_observation NOT IN (SELECT ce_proposition FROM _temp_having_retenue) */ \ |
GROUP BY ce_observation HAVING COUNT(id_commentaire) = 1); |
END; |
| |
DELIMITER ; |
CALL update_struct(); |
-- table temporaire de tous les comptages (somme des votes pour chaque proposition de del_commentaire): |
CREATE TEMPORARY TABLE IF NOT EXISTS _temp_stats ENGINE=MEMORY AS ( SELECT ce_proposition, SUM(valeur) AS val FROM `BASEDEL`.`del_commentaire_vote` GROUP BY ce_proposition); -- 5912 |
-- propositions ayant eu au moins 1 vote positif non-anonyme |
CREATE TEMPORARY TABLE IF NOT EXISTS _temp_authvotepos ENGINE=MEMORY AS (SELECT DISTINCT ce_proposition FROM `BASEDEL`.`del_commentaire_vote` WHERE valeur = 1 AND LENGTH(ce_utilisateur) != 32 ORDER BY ce_proposition); -- 3794 |
CALL rebuild_retenues(); -- initialisation |
-- core |
-- SELECT ce_observation, id_commentaire FROM `BASEDEL`.`del_commentaire` co INNER JOIN _temp_multi_prop mp USING (ce_observation) INNER JOIN `BASECEL`.`cel_obs` ce ON mp.ce_observation = id_observation AND (co.nom_sel = ce.nom_sel AND co.nom_sel_nn = ce.nom_sel_nn) WHERE co.nom_sel_nn != 0 AND co.proposition_retenue = 0; -- 470, dont 464 ce_observation unique |
-- SELECT ce_observation, id_commentaire FROM `BASEDEL`.`del_commentaire` co INNER JOIN _temp_multi_prop mp USING (ce_observation) INNER JOIN `BASECEL`.`cel_obs` ce ON mp.ce_observation = id_observation AND (co.nom_sel = ce.nom_sel OR co.nom_sel_nn = ce.nom_sel_nn) WHERE co.nom_sel_nn != 0 AND co.proposition_retenue = 0; -- 520, dont 493 ce_observation unique |
-- Étant donné les doublons nous pouvons commencer ou finir par filtrer sur les stats de vote |
-- Comme il est plus simple de finir par ça, commençons correctement par les nom_sel comme ci-dessus avec ceux sans ambiguité: |
-- C'est à dire observations dotées de multiples proposition dont une et une seule match exactement le nom-sel du carnet en ligne |
CREATE TEMPORARY TABLE IF NOT EXISTS _temp_updatable1 ENGINE=MEMORY AS ( \ |
SELECT /* ce_observation, */ id_commentaire FROM `BASEDEL`.`del_commentaire` co \ |
INNER JOIN _temp_multi_prop mp USING (ce_observation) /* faisant partie des observations ayant plusieurs propositions */ \ |
INNER JOIN `BASECEL`.`cel_obs` ce ON mp.ce_observation = id_observation AND (co.nom_sel = ce.nom_sel AND co.nom_sel_nn = ce.nom_sel_nn) \ |
WHERE co.nom_sel_nn != 0 \ |
GROUP BY co.ce_observation HAVING COUNT(co.id_commentaire) = 1 /* observations n'ayant pas d'ambiguité sur le commentaire correspondant au nom du carnet en ligne */ ); -- 335 |
UPDATE `BASEDEL`.`del_commentaire` co SET co.proposition_retenue = 1 WHERE co.id_commentaire IN (SELECT id_commentaire FROM _temp_updatable1); |
SELECT ROW_COUNT() AS "nb MAJ par match sur nom_sel sans ambiguité"; |
CALL rebuild_retenues(); |
-- Pour les observations ayant plusieurs nom-sel communs au carnet en ligne, il s'agit de ne sélectionner que celle |
-- ayant le plus de vote (idéalement les propositions doublonnes ne devraient pas exister) |
CREATE TEMPORARY TABLE IF NOT EXISTS _temp_updatable2 ENGINE=MEMORY AS ( \ |
SELECT co.ce_observation, id_commentaire, i1.val FROM `BASEDEL`.`del_commentaire` co \ |
INNER JOIN _temp_multi_prop mp USING (ce_observation) /* uniquement les multi-propositions, inclue le check sur _temp_having_retenue */ \ |
INNER JOIN (SELECT ce_proposition, val FROM _temp_stats) AS i1 ON i1.ce_proposition = co.id_commentaire /* et ayant des votes */ \ |
INNER JOIN `BASECEL`.`cel_obs` ce ON co.ce_observation = ce.id_observation AND (co.nom_sel = ce.nom_sel AND co.nom_sel_nn = ce.nom_sel_nn) /* et un nom_sel acceptable */ \ |
WHERE co.nom_sel_nn != 0 \ |
GROUP BY ce_observation HAVING i1.val = MAX(i1.val) /* parmis les doublonnes, prendre la proposition ayant le plus de SUM(votes) */ \ |
ORDER BY ce_observation ); -- 249 (sans le processus précédent, moins autrement s'il l'on exclue les observation déjà "validée") |
UPDATE `BASEDEL`.`del_commentaire` co SET co.proposition_retenue = 1 WHERE co.id_commentaire IN (SELECT id_commentaire FROM _temp_updatable2); |
SELECT ROW_COUNT() AS "nb MAJ par nombre de vote"; |
CALL rebuild_retenues(); |
-- Enfin, les observation n'ayant qu'une seule proposition sont passées comme retenues si |
-- elles ont été notée positivement au moins une fois par un utilisateur authentifié |
CREATE TEMPORARY TABLE IF NOT EXISTS _temp_updatable3 ENGINE=MEMORY AS ( \ |
SELECT co.id_commentaire FROM `BASEDEL`.`del_commentaire` co \ |
INNER JOIN _temp_mono_prop AS i1 USING (ce_observation) /* l'inverse de _temp_multi_prop, inclue le check sur _temp_having_retenue */ \ |
INNER JOIN _temp_authvotepos ta ON co.id_commentaire = ta.ce_proposition /* et uniquement si faisant partie des commentaires doté d'un vote positif non-anonyme */ \ |
INNER JOIN `BASECEL`.`cel_obs` ce ON co.ce_observation = ce.id_observation AND (co.nom_sel = ce.nom_sel AND co.nom_sel_nn = ce.nom_sel_nn) \ |
WHERE co.nom_sel_nn != 0); -- 2216 sans test sur cel_obs, 2193 avec |
UPDATE `BASEDEL`.`del_commentaire` co SET co.proposition_retenue = 1 WHERE co.id_commentaire IN (SELECT id_commentaire FROM _temp_updatable3); |
SELECT ROW_COUNT() AS "nb MAJ ayant 1 seule proposition mais un vote non-anonyme positif"; |
CALL rebuild_retenues(); |
/trunk/scripts/modules/maj/Makefile |
---|
19,7 → 19,18 |
o_maj1: clean o_201309-index-views |
cat $(fichiers_generes) > maj1.comp.sql |
# maj1 contient: 201310-propret.sql |
o_maj2: fichiers_generes = $(addsuffix .comp.sql,$(filter-out clean,$?)) |
o_maj2: clean o_201310-propret |
cat $(fichiers_generes) > maj2.comp.sql |
# SHOW INDEX FROM cel_obs WHERE Key_name = 'transmission'; |
# SHOW INDEX FROM cel_obs WHERE Key_name = 'date_transmission'; |
o_201309-index-views: |
$(call do_subst,201309-index-views.sql) > $@.comp.sql |
# SHOW COLUMNS FROM del_commentaire LIKE 'proposition_retenu'; |
o_201310-propret: |
$(call do_subst,201310-propret.sql) > $@.comp.sql |
/trunk/src/org/tela_botanica/del/client/vues/identiplante/moteur/MoteurIdentiplanteVue.java |
---|
30,7 → 30,7 |
Panel zoneRecherche, zoneResultats; |
@UiField |
Label ongletTout, ongletADeterminer, ongletEnDiscussion; |
Label ongletTout, ongletADeterminer, ongletEnDiscussion, ongletValidees; |
public HasWidgets getZoneRecherche() { |
return zoneRecherche; |
62,6 → 62,11 |
} |
@Override |
public HasClickHandlers getOngletValidees() { |
return ongletValidees; |
} |
@Override |
public void setOngletADeterminerActif() { |
nettoyerOngletsActifs(); |
ongletADeterminer.addStyleName("onglet-actif"); |
78,11 → 83,18 |
nettoyerOngletsActifs(); |
ongletEnDiscussion.addStyleName("onglet-actif"); |
} |
@Override |
public void setOngletValideesActif() { |
nettoyerOngletsActifs(); |
ongletValidees.addStyleName("onglet-actif"); |
} |
public void nettoyerOngletsActifs() { |
ongletTout.removeStyleName("onglet-actif"); |
ongletADeterminer.removeStyleName("onglet-actif"); |
ongletEnDiscussion.removeStyleName("onglet-actif"); |
ongletValidees.removeStyleName("onglet-actif"); |
} |
public void mettreAJourOngletEnFonctionDuCache() { |
93,6 → 105,8 |
setOngletADeterminerActif(); |
} else if (statut.equals("endiscussion")) { |
setOngletEnDiscussionActif(); |
} else if (statut.equals("validees")) { |
setOngletValideesActif(); |
} |
} |
/trunk/src/org/tela_botanica/del/client/vues/identiplante/moteur/MoteurIdentiplanteVue.ui.xml |
---|
17,6 → 17,7 |
<g:HTMLPanel styleName="zone-onglets"> |
<g:Label styleName="onglet onglet-actif" text="Tout" ui:field="ongletTout"></g:Label> |
<g:Label styleName="onglet" text="A déterminer" ui:field="ongletADeterminer"></g:Label> |
<g:Label styleName="onglet" text="Validées" ui:field="ongletValidees"></g:Label> |
<g:Label styleName="onglet" text="En discussion" ui:field="ongletEnDiscussion"></g:Label> |
</g:HTMLPanel> |
<g:HTMLPanel> |
/trunk/src/org/tela_botanica/del/client/vues/identiplante/moteur/MoteurIdentiplantePresenteur.java |
---|
33,6 → 33,8 |
public HasClickHandlers getOngletADeterminer(); |
public HasClickHandlers getOngletTout(); |
public HasClickHandlers getOngletValidees(); |
public void setOngletADeterminerActif(); |
39,6 → 41,8 |
public void setOngletToutActif(); |
public void setOngletEnDiscussionActif(); |
public void setOngletValideesActif(); |
} |
107,6 → 111,17 |
vue.setOngletEnDiscussionActif(); |
} |
}); |
vue.getOngletValidees().addClickHandler(new ClickHandler() { |
@Override |
public void onClick(ClickEvent event) { |
CacheClient.getInstance().setFiltreStatut("validees"); |
CacheClient.getInstance().setPageCouranteRechercheObservations(1); |
chercherObservations(); |
vue.setOngletValideesActif(); |
} |
}); |
} |
} |