Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/herited attr #284

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions apptax/migrations/versions/dbb7d939fef0_herited_attributes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
""" Create herited attributes view

Revision ID: dbb7d939fef0
Revises: 4fb7e197d241
Create Date: 2021-09-28 11:49:57.654351

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'dbb7d939fef0'
down_revision = '4fb7e197d241'
branch_labels = None
depends_on = None


def upgrade():
op.execute("""
CREATE MATERIALIZED VIEW taxonomie.taxref_tree
AS WITH RECURSIVE x AS (
SELECT t.cd_nom as cd_ref,
t.cd_nom::text::ltree AS path
FROM taxonomie.taxref t
WHERE t.cd_sup IS NULL AND t.cd_nom = t.cd_ref
UNION ALL
SELECT y.cd_nom AS cd_ref,
ltree_addtext(x_1.path, y.cd_nom::text) AS path
FROM x x_1,
taxonomie.taxref y
WHERE y.cd_nom = y.cd_ref AND x_1.cd_ref = y.cd_sup
)
SELECT x.cd_ref,
x.path
FROM x
WITH DATA;

-- View indexes:
CREATE UNIQUE INDEX taxref_tree_cd_nom_idx ON taxonomie.taxref_tree USING btree (cd_ref);
CREATE INDEX taxref_tree_path_idx ON taxonomie.taxref_tree USING gist (path); -- TRES important pour les perfs
""")
op.execute("""
ALTER TABLE taxonomie.bib_attributs ADD recursif BOOLEAN DEFAULT(false);
""")
op.execute("""
CREATE OR REPLACE VIEW taxonomie.v_recursif_cor_taxon_attribut AS
WITH rec_bib_nom AS (
SELECT p.cd_ref p_cd_ref, nlevel(p.path), bn.*
FROM taxonomie.taxref_tree child
JOIN taxonomie.bib_noms bn
ON child.cd_ref = bn.cd_ref
JOIN taxonomie.taxref_tree p
ON child.path <@ p.PATH
)
SELECT * -- Attributs hérités c-a-d avec la propriétée récursif à TRUE
FROM (
SELECT DISTINCT ON (n.cd_nom, n.cd_ref, cta.id_attribut) n.p_cd_ref, cta.id_attribut , cta.valeur_attribut , n.cd_ref
FROM taxonomie.cor_taxon_attribut cta
JOIN taxonomie.bib_attributs ba
ON ba.id_attribut = cta.id_attribut AND recursif IS TRUE
JOIN rec_bib_nom n
ON n.p_cd_ref = cta.cd_ref
ORDER BY n.cd_nom, cd_ref, cta.id_attribut , nlevel DESC
) AS h
UNION -- Attributs non hérités
SELECT cta.cd_ref, cta.id_attribut , cta.valeur_attribut , cta.cd_ref
FROM taxonomie.cor_taxon_attribut cta
JOIN taxonomie.bib_attributs ba
ON ba.id_attribut = cta.id_attribut AND recursif IS FALSE;
""")


def downgrade():
op.execute("""
DROP VIEW taxonomie.v_recursif_cor_taxon_attribut;
""")
op.execute("""
ALTER TABLE taxonomie.bib_attributs DROP COLUMN recursif;
""")
op.execute("""
DROP INDEX taxonomie.taxref_tree_cd_nom_idx;
DROP INDEX taxonomie.taxref_tree_path_idx;
DROP MATERIALIZED VIEW taxonomie.taxref_tree;
""")
28 changes: 28 additions & 0 deletions apptax/taxonomie/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class BibNoms(serializableModel, db.Model):

taxref = db.relationship("Taxref", lazy="select")
attributs = db.relationship("CorTaxonAttribut", lazy="select")
h_attributs = db.relationship("VHeritedCorTaxonAttribut", lazy="select")
listes = db.relationship("CorNomListe", lazy="select")
medias = db.relationship("TMedias", lazy="select")

Expand All @@ -47,6 +48,33 @@ class CorTaxonAttribut(serializableModel, db.Model):
def __repr__(self):
return "<CorTaxonAttribut %r>" % self.valeur_attribut

class VHeritedCorTaxonAttribut(serializableModel, db.Model):
__tablename__ = "v_recursif_cor_taxon_attribut"
__table_args__ = {"schema": "taxonomie"}
id_attribut = db.Column(
db.Integer,
ForeignKey("taxonomie.bib_attributs.id_attribut"),
nullable=False,
primary_key=True,
)
cd_ref = db.Column(
db.Integer,
ForeignKey("taxonomie.bib_noms.cd_ref"),
nullable=False,
primary_key=True,
)
p_cd_ref = db.Column(
db.Integer
)
valeur_attribut = db.Column(db.Text, nullable=False)
bib_nom = db.relationship("BibNoms")
bib_attribut = db.relationship("BibAttributs")

def __repr__(self):
return "<VHeritedCorTaxonAttribut %r>" % self.valeur_attribut




class BibAttributs(serializableModel, db.Model):
__tablename__ = "bib_attributs"
Expand Down
2 changes: 1 addition & 1 deletion apptax/taxonomie/routesbibattributs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from sqlalchemy import select, or_

from ..utils.utilssqlalchemy import json_resp
from .models import BibNoms, Taxref, CorTaxonAttribut, BibAttributs
from .models import BibAttributs

from . import db
adresses = Blueprint('bib_attribut', __name__)
Expand Down
12 changes: 6 additions & 6 deletions apptax/taxonomie/routesbibnoms.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from .models import (
BibNoms,
Taxref,
CorTaxonAttribut,
CorTaxonAttribut, VHeritedCorTaxonAttribut,
BibThemes,
CorNomListe,
BibAttributs,
Expand Down Expand Up @@ -121,19 +121,19 @@ def getOne_bibtaxonsInfo(cd_nom):
cd_ref = db.session.query(Taxref.cd_ref).filter_by(cd_nom=cd_nom).first()
obj = {}

# A out des attributs
# Ajout des attributs
obj["attributs"] = []
q = db.session.query(CorTaxonAttribut).filter_by(cd_ref=cd_ref)
q = db.session.query(VHeritedCorTaxonAttribut).filter_by(cd_ref=cd_ref)
join_on_bib_attr = False
if "id_theme" in request.args.keys() :
q = q.join(
BibAttributs, BibAttributs.id_attribut == CorTaxonAttribut.id_attribut
BibAttributs, BibAttributs.id_attribut == VHeritedCorTaxonAttribut.id_attribut
).filter(BibAttributs.id_theme.in_( request.args.getlist("id_theme") ))
join_on_bib_attr = True
if "id_attribut" in request.args.keys() :
if not join_on_bib_attr:
q = q.join(
BibAttributs, BibAttributs.id_attribut == CorTaxonAttribut.id_attribut
BibAttributs, BibAttributs.id_attribut == VHeritedCorTaxonAttribut.id_attribut
)
q = q.filter(BibAttributs.id_attribut.in_( request.args.getlist("id_attribut") ))
bibAttr = q.all()
Expand Down Expand Up @@ -184,7 +184,7 @@ def getOneFull_bibtaxons(id_nom):

# Ajout des attributs
obj["attributs"] = []
for attr in bibTaxon.attributs:
for attr in bibTaxon.h_attributs:
o = dict(attr.as_dict().items())
o.update(dict(attr.bib_attribut.as_dict().items()))
id = o["id_theme"]
Expand Down
2 changes: 1 addition & 1 deletion static/app/bib_nom/detail/bibNom-detail-tpl.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ <h3 class="col-md-9 modal-title">{{ctrl.bibNom.taxref.nom_complet}}</h3>
<div class="panel-body ">
<table class="table table-striped ">
<tr ng-repeat="attribut in value | orderBy : 'ordre'">
<th class="col-md-4">{{attribut.label_attribut}}</th>
<th class="col-md-4">{{attribut.label_attribut}}<span ng-if="attribut.cd_ref !== attribut.p_cd_ref">(Hérité)</span></th>
<td class="col-md-6">{{attribut.valeur_attribut}}</td>
</tr>
</table>
Expand Down
11 changes: 10 additions & 1 deletion static/app/bib_nom/edit/bibNom-form-controler.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ function($scope, $routeParams, $http, $uibModal, locationHistoryService, $locati
self.mediasPath = backendCfg.medias_path;
self.bibNom = {};
self.bibNom.attributs_values = {};
self.bibNom.herited_attributs_values = {};
self.previousLocation = locationHistoryService.get();
self.hideSave = false;
self.hideSaveButton = function(){self.hideSave = true;}
Expand Down Expand Up @@ -38,10 +39,18 @@ function($scope, $routeParams, $http, $uibModal, locationHistoryService, $locati
self.bibNom.medias = response.data.medias;
}
self.bibNom.attributs_values = {};
self.bibNom.herited_attributs_values = {};
if (response.data.attributs) {
angular.forEach(response.data.attributs, function(value, key) {
if (value.type_widget==="number") value.valeur_attribut = Number(value.valeur_attribut);
if (value.type_widget==="number") {
value.valeur_attribut = Number(value.valeur_attribut);
}
if (value.cd_ref !== value.p_cd_ref) {
self.bibNom.herited_attributs_values[value.id_attribut] = value.valeur_attribut;
}
else {
self.bibNom.attributs_values[value.id_attribut] = value.valeur_attribut;
}
});
delete self.bibNom.attributs;
}
Expand Down
1 change: 1 addition & 0 deletions static/app/bib_nom/edit/bibNom-form-tpl.html
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
<div create-bibNoms-attr-form-dir
attributs-def-list="ctrl.attributsDefList"
attributs-values="ctrl.bibNom.attributs_values"
herited-attributs-values="ctrl.bibNom.herited_attributs_values"
userrightlevel="ctrl.userRightLevel"
ng-if="ctrl.attributsDefList">
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ app.directive('createBibnomsAttrFormDir', [function () {
scope : {
attributsDefList:'=',
attributsValues:'=',
heritedAttributsValues:'=',
userrightlevel:'='
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,68 +12,76 @@
</uib-accordion-heading>
<div ng-repeat="attrdef in value.attributs | orderBy : 'ordre'" class="panel-body ">
<label class="col-sm-2 control-label" for="sm" id="lbl-{{attrdef.id_attribut}}">{{attrdef.label_attribut}}</label>
<div class="col-sm-10">
<ng-switch on="attrdef.type_widget">
<span ng-switch-when="radio">
<label ng-repeat="radval in attrdef.listeValeurObj.values" class="radio-inline">
<input type="radio"
name="value-{{attrdef.id_attribut}}"
ng-model="attributsValues[attrdef.id_attribut]"
ng-required="{{attrdef.obligatoire}} "
value="{{radval}}">
{{radval}}
</label>
</span>

<span ng-switch-when="checkbox">
<input-checkbox-dir
attr-def-list="attrdef.listeValeurObj.values"
value = "attributsValues[attrdef.id_attribut]"
/>
</span>
<div class="col-sm-10">

<span ng-switch-when="select">
<select class="form-control"
<div class="alert alert-warning" role="alert" ng-if="heritedAttributsValues[attrdef.id_attribut]">
<strong>Valeur Héritée : </strong>{{heritedAttributsValues[attrdef.id_attribut]}}
</div>
<div >
<ng-switch on="attrdef.type_widget">
<span ng-switch-when="radio">
<label ng-repeat="radval in attrdef.listeValeurObj.values" class="radio-inline">
<input type="radio"
name="value-{{attrdef.id_attribut}}"
ng-model="attributsValues[attrdef.id_attribut]"
ng-options="value as value for (key, value) in attrdef.listeValeurObj.values | orderBy: 'toString()'"
ng-required="{{attrdef.obligatoire}}">
<option value="">-- selectionnez {{attrdef.nom_attribut}} --</option>
</select>
</span>
ng-required="{{attrdef.obligatoire}} "
value="{{radval}}">
{{radval}}
</label>
</span>

<span ng-switch-when="checkbox">
<input-checkbox-dir
attr-def-list="attrdef.listeValeurObj.values"
value = "attributsValues[attrdef.id_attribut]"
/>
</span>

<span ng-switch-when="multiselect">
<input-multiselect-dir
attr-def-list="attrdef.listeValeurObj.values"
value = "attributsValues[attrdef.id_attribut]"
/>
</span>
<span ng-switch-when="select">
<select class="form-control"
ng-model="attributsValues[attrdef.id_attribut]"
ng-options="value as value for (key, value) in attrdef.listeValeurObj.values | orderBy: 'toString()'"
ng-required="{{attrdef.obligatoire}}">
<option value="">-- selectionnez {{attrdef.nom_attribut}} --</option>
</select>
</span>

<span ng-switch-when="text">
<input class="form-control" type="text"
id="value-{{attrdef.id_attribut}}" ng-model="attributsValues[attrdef.id_attribut]"
ng-required="{{attrdef.obligatoire}}"/>
</span>
<span ng-switch-when="multiselect">
<input-multiselect-dir
attr-def-list="attrdef.listeValeurObj.values"
value = "attributsValues[attrdef.id_attribut]"
/>
</span>

<span ng-switch-when="textarea">
<textarea class="form-control" rows="3"
id="value-{{attrdef.id_attribut}}" ng-model="attributsValues[attrdef.id_attribut]"
ng-required="{{attrdef.obligatoire}}"> </textarea>
</span>
<span ng-switch-when="text">
<input class="form-control" type="text"
id="value-{{attrdef.id_attribut}}" ng-model="attributsValues[attrdef.id_attribut]"
ng-required="{{attrdef.obligatoire}}"/>
</span>

<span ng-switch-when="number">
<input class="form-control" type="number"
id="value-{{attrdef.id_attribut}}" name="value-{{attrdef.id_attribut}}"
ng-model="attributsValues[attrdef.id_attribut]"
min="{{attrdef.listeValeurObj.min}}" max="{{attrdef.listeValeurObj.max}}"
ng-required="{{attrdef.obligatoire}}"/>
</span>
<span ng-switch-when="textarea">
<textarea class="form-control" rows="3"
id="value-{{attrdef.id_attribut}}" ng-model="attributsValues[attrdef.id_attribut]"
ng-required="{{attrdef.obligatoire}}"> </textarea>
</span>

<span ng-switch-when="phenology">
<input-phenology string-value="attributsValues[attrdef.id_attribut]"></input-phenology>
</span>
<span ng-switch-default>TYPE NOT FOUND {{attrdef.type_widget}}</span>
<span ng-switch-when="number">
<input class="form-control" type="number"
id="value-{{attrdef.id_attribut}}" name="value-{{attrdef.id_attribut}}"
ng-model="attributsValues[attrdef.id_attribut]"
min="{{attrdef.listeValeurObj.min}}" max="{{attrdef.listeValeurObj.max}}"
ng-required="{{attrdef.obligatoire}}"/>
</span>

<span ng-switch-when="phenology">
<input-phenology string-value="attributsValues[attrdef.id_attribut]"></input-phenology>
</span>
<span ng-switch-default>TYPE NOT FOUND {{attrdef.type_widget}}</span>

</ng-switch>
</ng-switch>
</div>
</div>

</div>
</uib-accordion>