Commit 2d3a829a by François C.

Allow member to switch shift template subscription and other changes to customize for Supercoop

parent 2a9168ae
Pipeline #2365 failed with stage
in 1 minute 25 seconds
......@@ -495,14 +495,19 @@ def shift_subscription(request):
and delete all existing shifts EXCEPT makeups.
"""
res = {}
if CagetteUser.are_credentials_ok(request):
data = json.loads(request.body.decode())
data = json.loads(request.body.decode())
partner_id = int(data["partner_id"])
is_allowed = CagetteUser.are_credentials_ok(request)
if is_allowed is False:
credentials = CagetteMember.get_credentials(request, with_id = True)
if 'success' in credentials and credentials['success'] is True and credentials['id'] == partner_id:
is_allowed = True
if is_allowed is True:
partner_id = int(data["partner_id"])
shift_type = data["shift_type"]
if shift_type == 1:
# 1 = standard
shift_template_id = data["shift_template_id"]
shift_template_id = int(data["shift_template_id"])
else:
# 2 = ftop
......@@ -530,7 +535,6 @@ def shift_subscription(request):
)
res["unsubscribe_member"] = m.unsubscribe_member(changing_shift = True)
m.create_coop_shift_subscription(shift_template_id, shift_type)
# Return necessary data
......
......@@ -121,7 +121,7 @@ class CagetteMember(models.Model):
'id DESC')
@staticmethod
def get_credentials(request, external=False):
def get_credentials(request, external=False, with_id=False):
import hashlib
data = {}
......@@ -191,6 +191,8 @@ class CagetteMember(models.Model):
calc_token = hashlib.sha256(res[0]['create_date'].encode('utf-8')).hexdigest()
if calc_token == request.COOKIES['token']:
data['success'] = True
if with_id is True:
data['id'] = res[0]['id']
else:
data['failure'] = True
data['errnum'] = 3
......
var calendar = null;
function init_my_shifts_tile() {
if (incoming_shifts.length === 0) {
$("#home_tile_my_services #home_incoming_services").text("Aucun service à venir...");
......@@ -20,6 +22,95 @@ function init_my_shifts_tile() {
}
}
function process_asked_shift_template_change(shift_t_id) {
var s_data = shift_templates[shift_t_id].data;
var shift_name = get_shift_name(s_data);
let msg = 'Inscription au créneau ' + shift_name
openModal(
msg,
function() {
let data = {
partner_id: parseInt(partner_data.partner_id, 10),
shift_type: 1, //force to standard
shift_template_id: shift_t_id,
unsubscribe_first: true
};
$.ajax({
type: 'POST',
url: '/members/shift_subscription',
data: JSON.stringify(data),
dataType:"json",
traditional: true,
contentType: "application/json; charset=utf-8",
success: function(data) {
stdata = data.shift_template;
partner_data.regular_shift_name = stdata.name;
partner_data.shift_type = "standard";
init_my_info_data();
closeModal();
setTimeout(() => {
$.notify("Inscription au nouveau service réussie.", {
globalPosition:"top right",
className: "success"
});
}, 200);
},
error: function(err_data) {
if (
err_data.status == 409
&& typeof (err_data.responseJSON) != "undefined"
&& err_data.responseJSON.code === "makeup_found"
) {
let modal_template = $("#modal_error_change_shift_template");
modal_template.find(".shift_template_name").text(shift_template_name);
closeModal();
openModal(
modal_template.html(),
() => {},
"Compris !",
true,
false
);
} else {
err = {
msg: "erreur serveur lors de l'inscription du membre au créneau",
ctx: 'members_space.shift_subscrition'
};
report_JS_error(err, 'members_space');
closeModal();
$.notify("Une erreur est survenue lors de l'inscription au créneau.", {
globalPosition:"top right",
className: "error"
});
}
}
});
}
);
}
function edit_shift_template_registration(){
let external = true;
if (calendar == null) calendar = $('#modal-calendar-choice').clone();
if ($('#modal-calendar-choice').html().length > 0) {
$('#modal-calendar-choice').empty();
}
calendar.find('.oddeven_selector').empty();
displayMsg(calendar.html());
$('#week_types').find('input').change(()=>{filter_weeks(external)});
retrieve_and_draw_shift_tempates(external);
}
function init_home() {
$("#go_to_shifts_calendar").on("click", () => {
goto('echange-de-services');
......@@ -37,6 +128,12 @@ function init_home() {
goto('faq');
});
$(".member_shift_name_area").on("click", ".fa-edit", (e) => {
$('#week_types').find('input').change(filter_weeks);
e.preventDefault();
edit_shift_template_registration();
});
if (partner_data.is_in_association === false) {
$("#home .member_associated_partner_area").hide();
} else {
......
......@@ -120,6 +120,7 @@ def index(request, exception=None):
m = CagetteMembersSpace()
context['show_faq'] = getattr(settings, 'MEMBERS_SPACE_FAQ_TEMPLATE', 'members_space/faq.html')
context['show_abcd_calendar'] = getattr(settings, 'SHOW_ABCD_CALENDAR_TAB', True)
partnerData["comite"] = m.is_comite(partner_id)
context['partnerData'] = partnerData
......@@ -174,6 +175,8 @@ def home(request):
template = loader.get_template(getattr(settings, 'MEMBERS_SPACE_HOME_TEMPLATE', 'members_space/home.html'))
context = {
'title': 'Espace Membres',
'coop_can_change_shift_template': getattr(settings, 'COOP_CAN_CHANGE_SHIFT_TEMPLATE', False),
'max_begin_hour': settings.MAX_BEGIN_HOUR,
}
# Get messages to display
msettings = MConfig.get_settings('members')
......@@ -188,7 +191,8 @@ def my_info(request):
template = loader.get_template('members_space/my_info.html')
context = {
'title': 'Mes Infos',
'understand_my_status': getattr(settings, 'MEMBERS_SPACE_SHOW_UNDERSTAND_MY_STATUS', True)
'understand_my_status': getattr(settings, 'MEMBERS_SPACE_SHOW_UNDERSTAND_MY_STATUS', True),
'understand_my_status_template': getattr(settings, 'MEMBERS_SPACE_UNDERSTAND_MY_STATUS_TEMPLATE', "members_space/understand_my_status.html")
}
return HttpResponse(template.render(context, request))
......
......@@ -423,8 +423,24 @@
- START_DATE_FOR_SHIFTS_HISTORY = "2018-01-01"
- AMNISTIE_DATE = "2021-11-24 00:00:00"
In members_space history display a special activity about amnistie
- MEMBERS_SPACE_FAQ_TEMPLATE = 'members_space/supercoop/faq.html'
Set alternative template for FAQ
- MEMBERS_SPACE_HOME_TEMPLATE = 'members_space/supercoop/home.html'
Set alternative template for home page
- MEMBERS_SPACE_UNDERSTAND_MY_STATUS_TEMPLATE = 'members_space/supercoop/understand_my_status.html'
Set alternative template for understand my status
- SHOW_ABCD_CALENDAR_TAB = False
True by default
### BDM Admin
......
......@@ -23,7 +23,7 @@ var volant = null;
function get_displayed_weeks() {
displayed_weeks = [];
week_types.find('.selected_weeks :checked').each(function() {
$('#week_types').find('.selected_weeks :checked').each(function() {
displayed_weeks.push($(this).val());
});
......@@ -32,7 +32,7 @@ function get_displayed_weeks() {
function get_shift_name(s_data) {
var shift_name = "Inconnu";
if (typeof ASSOCIATE_MEMBER_SHIFT == "undefined") ASSOCIATE_MEMBER_SHIFT = "";
if (s_data && s_data.week) {
shift_name = weeks_name[s_data.week];
if (s_data.type == 2 && typeof manage_ftop != "undefined" && manage_ftop == true && s_data.id != ASSOCIATE_MEMBER_SHIFT) {
......@@ -112,7 +112,7 @@ function select_shift_among_compact(event, clicked_item = null, subscribe = true
var worst_score = 1;
displayed_weeks = get_displayed_weeks();
var place_cond = sc_lat.find('.highlighted').data('select');
var place_cond = sc_lat.find('.highlighted').data('select') || "";
$.each(shift_templates, function(i, e) {
if (e.data) {
......@@ -135,14 +135,23 @@ function select_shift_among_compact(event, clicked_item = null, subscribe = true
}
});
if (selected && subscribe === true)
subscribe_shift(selected);
if (selected && subscribe === true){
if (typeof partner_data !== "undefined" && typeof partner_data.barcode_base !== "undefined") {
//click is coming from memberspace
process_asked_shift_template_change(selected);
} else {
subscribe_shift(selected);
}
}
return selected
}
function draw_table(begin_hours, callback) {
if (shift_table.length == 0) shift_table = $('#shift_choice table');
shift_table.find('tbody tr').remove();
begin_hours.sort();
var days = [
......@@ -172,14 +181,15 @@ function draw_table(begin_hours, callback) {
}
function draw_shift_templates() {
function draw_shift_templates(external) {
if (typeof external !== "undefined" && external == true) shift_table = $('#shift_choice table');
var existing_shifts = shift_table.find('.shift');
existing_shifts.off("click", single_shift_click);
existing_shifts.off("click", select_shift_among_compact);
existing_shifts.remove();
var place_cond = sc_lat.find('.highlighted').data('select');
var place_cond = sc_lat.find('.highlighted').data('select') || "";
//warning MAG_NAME should correspond to data.place value of shift_templates objects
dispo = 0;
......@@ -199,7 +209,7 @@ function draw_shift_templates() {
if (e.data.begin <= max_begin_hour && e.data.max > 0 && (place_cond == 'both' || place_cond == place)) {
keep_it = true;
}
}
if (keep_it == true && displayed_weeks.indexOf(e.data.week.toString()) > -1) {
var known_begin_hour = false;
......@@ -272,7 +282,6 @@ function draw_shift_templates() {
boxes[e.data.day+'_'+e.data.begin]['profil'] = profile;
}
}
}
}
......@@ -280,6 +289,7 @@ function draw_shift_templates() {
}
});
if (type == 1) {
shift_table.find('.shift').on("click", single_shift_click);
}
......@@ -311,16 +321,19 @@ function draw_shift_templates() {
sc_lat.find('.info').html(dispo + ' places disponibles<br />(/'+max+')');
closeModal();
if (typeof external == "undefined") {
closeModal();
}
});
}
function retrieve_and_draw_shift_tempates() {
openModal();
function retrieve_and_draw_shift_tempates(external) {
if (shift_table.length == 0) shift_table = $('#shift_choice table');
if (!external) {
openModal();
}
shift_table.find('.shift').remove();
......@@ -333,7 +346,7 @@ function retrieve_and_draw_shift_tempates() {
if (e.data.type == 2 && volant == null) {
// has comitee shift
if (committees_shift_id !== undefined && committees_shift_id !== "None") {
if (typeof committees_shift_id !== "undefined" && committees_shift_id !== "None") {
if (e.data.id == parseInt(committees_shift_id)) {
volant = e.data.id
}
......@@ -342,33 +355,36 @@ function retrieve_and_draw_shift_tempates() {
}
}
});
dbc.allDocs({include_docs: true, descending: true}, function(err, resp) {
if (err) {
return console.log(err);
}
$.each(resp.rows, function(i, e) {
if (e.doc.shift_template && typeof(e.doc.shift_template.data) != "undefined") {
try {
if (typeof shift_templates[e.doc.shift_template.data.id]!= "undefined")
shift_templates[e.doc.shift_template.data.id]['data']['reserved'] += 1;
} catch (ec) {
console.log(ec);
}
if (typeof dbc !== "undefined") {
dbc.allDocs({include_docs: true, descending: true}, function(err, resp) {
if (err) {
return console.log(err);
}
$.each(resp.rows, function(i, e) {
if (e.doc.shift_template && typeof(e.doc.shift_template.data) != "undefined") {
try {
if (typeof shift_templates[e.doc.shift_template.data.id]!= "undefined")
shift_templates[e.doc.shift_template.data.id]['data']['reserved'] += 1;
} catch (ec) {
console.log(ec);
}
}
});
draw_shift_templates(external);
});
draw_shift_templates();
});
} else {
draw_shift_templates(external);
}
});
}
function filter_weeks() {
function filter_weeks(external) {
var clicked = $(this);
var week_types = $('#week_types');
var parent_div = clicked.closest('div');
var w1 = week_types.find('#dw1');
var w2 = week_types.find('#dw2');
......@@ -411,8 +427,7 @@ function filter_weeks() {
if (!w2.is(':checked') || !w4.is(':checked')) {
$('#odd_weeks').prop('checked', false);
}
draw_shift_templates();
draw_shift_templates(external);
}
function shift_loc_selection() {
......
......@@ -79,7 +79,7 @@
</div>
</div>
<div id="modal_error_change_shift_template">
<h3 class="error_modal_title""">Action impossible</h3>
<h3 class="error_modal_title">Action impossible</h3>
<p>
Le ou la membre est inscrit.e à un rattrapage sur le créneau choisi (<span class="shift_template_name"></span>), cela empêche de l'inscrire sur ce créneau.
</p>
......
<table class="table">
<caption>Calendrier fixe</caption>
<thead>
<tr>
<th scope="col" class="firstcol"></th>
<th scope="col">Lundi</th>
<th scope="col">Mardi</th>
<th scope="col">Mercredi</th>
<th scope="col">Jeudi</th>
<th scope="col">Vendredi</th>
<th scope="col">Samedi</th>
{% if open_on_sunday %}
<th scope="col">Dimanche</th>
{% endif %}
</tr>
</thead>
<tbody>
</tbody>
</table>
<div id="week_types" class="clearfix">
<div class="oddeven_selector fl">
<input type="checkbox" class="switch" id="even_weeks" value='0' checked><label for="even_weeks">Paires</label>
<input type="checkbox" class="switch" id="odd_weeks" value='1' checked><label for="odd_weeks">Impaires</label>
</div>
<div class="selected_weeks fl">
<input type="checkbox" class="switch" id="dw1" value='1' checked><label for="c1">A</label>
<input type="checkbox" class="switch" id="dw2" value='2' checked><label for="c2">B</label>
<input type="checkbox" class="switch" id="dw3" value='3' checked><label for="c3">C</label>
<input type="checkbox" class="switch" id="dw4" value='4' checked><label for="c4">D</label>
</div>
</div>
{% if type and type == 1 %}
<!--<div class="clearfix mtop25">Le trait <span class="alert">rouge</span> signale que le créneau est rempli à moins de 75%</div>-->
{% endif %}
\ No newline at end of file
......@@ -12,41 +12,7 @@
<div class="info"></div>
</div>
<div class="col-5 main_content">
<table class="table">
<caption>Calendrier fixe</caption>
<thead>
<tr>
<th scope="col" class="firstcol"></th>
<th scope="col">Lundi</th>
<th scope="col">Mardi</th>
<th scope="col">Mercredi</th>
<th scope="col">Jeudi</th>
<th scope="col">Vendredi</th>
<th scope="col">Samedi</th>
{% if open_on_sunday %}
<th scope="col">Dimanche</th>
{% endif %}
</tr>
</thead>
<tbody>
</tbody>
</table>
<div id="week_types" class="clearfix">
<div class="oddeven_selector fl">
<input type="checkbox" class="switch" id="even_weeks" value='0' checked><label for="even_weeks">Paires</label>
<input type="checkbox" class="switch" id="odd_weeks" value='1' checked><label for="odd_weeks">Impaires</label>
</div>
<div class="selected_weeks fl">
<input type="checkbox" class="switch" id="dw1" value='1' checked><label for="c1">A</label>
<input type="checkbox" class="switch" id="dw2" value='2' checked><label for="c2">B</label>
<input type="checkbox" class="switch" id="dw3" value='3' checked><label for="c3">C</label>
<input type="checkbox" class="switch" id="dw4" value='4' checked><label for="c4">D</label>
</div>
</div>
{% if type and type == 1 %}
<!--<div class="clearfix mtop25">Le trait <span class="alert">rouge</span> signale que le créneau est rempli à moins de 75%</div>-->
{% endif %}
{% include "members/shift_template_calendar.html" %}
</div>
</section>
\ No newline at end of file
......@@ -13,6 +13,7 @@
{% if show_faq %}
<a href="javascript:void(0);" class="nav_item" id="nav_faq">Problèmes et Demandes</a>
{% endif %}
{% if show_abcd_calendar %}
<a
href="javascript:void(0);"
target="_blank"
......@@ -21,7 +22,7 @@
>
Calendrier ABCD
</a>
{% endif %}
{# Disconnection button must have this id (logic in all_common.js) #}
<a href="javascript:void(0);" id="deconnect">Déconnexion</a>
<a href="javascript:void(0);" class="icon" onclick="toggleHeader()">
......
......@@ -28,6 +28,9 @@
<div class="member_shift_name_area">
<span>Mon créneau : </span>
<span class="member_shift_name member_info"></span>
{% if coop_can_change_shift_template %}
<span><i class="fas fa-edit tile_icon edit-btn"></i></span>
{% endif %}
</div>
<div class="member_coop_number_area">
<span>Mon numéro de coop : </span>
......@@ -118,4 +121,15 @@
</div>
</div>
</div>
{% if coop_can_change_shift_template %}
<div id="modal-calendar-choice" style="display:none;">
<div id="shift_choice">
{% include "members/shift_template_calendar.html" %}
</div>
</div>
<script>
var max_begin_hour = "{{max_begin_hour}}",
type = 2;
</script>
{% endif %}
</div>
......@@ -17,6 +17,7 @@
<script type="text/javascript" src="{% static 'js/datatables/dataTables.responsive.min.js' %}"></script>
<script type="text/javascript" src="{% static 'fullcalendar-5.9.0/lib/main.min.js' %}"></script>
<script type="text/javascript" src="{% static 'fullcalendar-5.9.0/lib/locales/fr.js' %}"></script>
<script type="text/javascript" src="{% static 'js/notify.min.js' %}?v=1651853225"></script>
{% endblock %}
{% block content %}
......@@ -156,6 +157,7 @@
const canAddShift = {{canAddShift}};
</script>
<script src="{% static "js/all_common.js" %}?v=1651853225"></script>
<script src="{% static "js/common.js" %}?v=1651853225"></script>
<script src="{% static "js/members-space-home.js" %}?v=1651853225"></script>
<script src="{% static "js/members-space-my-info.js" %}?v=1651853225"></script>
<script src="{% static "js/members-space-my-shifts.js" %}?v=1651853225"></script>
......
......@@ -106,7 +106,7 @@
</div>
</div>
{% if understand_my_status %}
{% include "members_space/understand_my_status.html" %}
{% include ""|add:understand_my_status_template %}
{% endif %}
</div>
</div>
<div id="faqBDM" class=" mt-3">
<div class="page_title txtcenter"><h1> Problèmes et demandes </h1></div>
<div class="tiles_container">
<div class="tile full_width_tile">
<p>
<a href="https://supercoop.notion.site/supercoop/Foire-Aux-Questions-sur-la-participation-et-Formulaires-correspondants-106143413d0b400a9f94023962375304" target="_blank">Foire-Aux-Questions-sur-la-participation-et-Formulaires</a>
</p>
<p>
<em>En cliquant sur le lien ci-dessus, un nouvel onglet ou une nouvelle fenêtre affichera le contenu de la page sur le site supercoop.notion.site.</em>
</p>
</div>
</div>
</div>
<div id="home">
<div class="page_title txtcenter">
<h1>Bienvenue sur ton nouvel espace membre ! 🎉</h1>
Si tu es ex-volant.e, il te faut absolument changer ton créneau volant (DDim 22:00)par un créneau régulier qui te convient ou le moins pire... (ci-dessous)<br/> Ensuite, tu peux déplacer ton prochain service programmé en allant sur "Echanges de services" 🤙<br/>
Si tu es régulier.e, rien ne change pour toi si ce n'est que tu peux anticiper une absence en déplaçant ton service. Tu n'as plus à rechercher de remplaçant ✌️<br/>
Concernant les binômes, il nous faut un peu plus de temps pour déployer cette nouveauté. On te tiens au courant via le mail hebdo 😉<br/>
Si jamais ça ne marche pas, contactes-nous à support@supercoop.fr 📧<br/>
</div>
<div>
</div>
<div class="tiles_container">
<div class="tile high_tile" id="home_tile_my_info">
<div class="tile_title">
<i class="fas fa-user tile_icon"></i>
<span class="member_info member_name"></span>
</div>
<div class="tile_content">
{# <p><span class="member_info member_name"></span></p> #}
<p class="member_status_text_container">Mon statut : <span class="member_info member_status"></span></p>
<div class="delay_date_stop_container">
( jusqu'au <span class="delay_date_stop"></span> )
</div>
<div id="member_status_action">
<a href="#" target="_blank" class="btn--warning unsuscribed_form_link">
J'accède au formulaire
</a>
<button type="button" class="btn--danger choose_makeups">
Je sélectionne mes rattrapages
</button>
<button type="button" class="btn--success remove_future_registration">
J'ai validé un service à deux, je peux supprimer une présence
</button>
</div>
<div class="member_shift_name_area">
<span>Mon créneau : </span>
<span class="member_shift_name member_info"></span>
{% if coop_can_change_shift_template %}
<span><i class="fas fa-edit tile_icon edit-btn"></i></span>
{% endif %}
</div>
<div class="member_coop_number_area">
<span>Mon numéro de coop : </span>
<span class="member_coop_number member_info"></span>
</div>
<div class="member_associated_partner_area">
<span>Je suis en binôme avec : </span>
<span class="member_associated_partner member_info"></span>
</div>
<div id="see_more_info">
<button type="button", class="btn btn--primary home_link_button" id="see_more_info_link">
Accéder à mes infos et comprendre mon statut
</button>
</div>
</div>
</div>
<div class="tile high_tile" id="home_tile_my_services">
<div class="tile_title">
<i class="fas fa-clipboard tile_icon"></i>
Mes Services
</div>
<div class="tile_content">
<h3>Services à venir</h3>
<div id="home_incoming_services">
<i class="fas fa-spinner fa-spin fa-lg"></i>
</div>
<div id="go_to_shift_history_area">
<button type="button", class="btn btn--primary" id="home_go_to_shift_history">
Accéder à mon historique
</button>
</div>
</div>
</div>
<div class="tile small_tile" id="home_tile_services_exchange">
<div class="tile_title">
<i class="fas fa-exchange-alt tile_icon"></i>
Échange de services
</div>
<div class="tile_content">
<div>
Un empêchement ? J'anticipe et déplace mes services jusqu'à 24h avant leur début !
</div>
<div class="home_link_button_area">
<button type="button" class="btn--primary home_link_button" id="go_to_shifts_calendar">
Accéder au calendrier d'échange de services
</button>
</div>
</div>
</div>
<div class="tile small_tile" id="home_tile_help">
<div class="tile_title">
<i class="fas fa-question-circle tile_icon"></i>
J'ai une demande
</div>
<div class="tile_content">
<div class="home_link_button_area">
<a
href="javascript:void(0);"
class="btn--primary home_link_button"
id="go_to_forms"
>
Accéder aux formulaires
</a>
</div>
</div>
</div>
<div class="tile small_tile" id="home_tile_shop_info">
<div class="tile_title">
<i class="fas fa-newspaper tile_icon"></i>
Informations magasins
</div>
<div id="shop_info_content">
<div class="shop_info_item shop_opening_hours">
<div class="shop_info_item_content">
<div class="opening_hours_title">
Horaires du magasin :
</div>
<div class="opening_hours_content">
{{shop_opening_hours|safe}}
</div>
</div>
</div>
<div class="shop_info_item shop_message">
<div class="shop_info_item_content shop_message_content">
{{msg_accueil|safe}}
</div>
</div>
</div>
</div>
</div>
{% if coop_can_change_shift_template %}
<div id="modal-calendar-choice" style="display:none;">
<div id="shift_choice">
{% include "members/shift_template_calendar.html" %}
</div>
</div>
<div id="modal_error_change_shift_template" style="display:none;">
<h3 class="error_modal_title">Action impossible</h3>
<p>
Il y a un rattrapage sur le créneau choisi (<span class="shift_template_name"></span>), cela empêche de s'inscrire sur ce créneau.
</p>
<p>Vous pouvez essayer ce créneau une autre semaine.</p>
</div>
<script>
var max_begin_hour = "{{max_begin_hour}}",
type = 2;
</script>
{% endif %}
</div>
<div class="tile full_width_tile">
<div class="tile_title">
Comprendre mon statut
</div>
<div class="my_info_line_middle">
Il existe différents statuts donnant ou non le droit de faire ses courses. Voici un schéma explicatif expliquant le passage d'un statut à un autre. Pour toute question relative aux statuts, rendez&#x2011;vous dans la rubrique <a href='faq'>Problèmes&nbsp;&&nbsp;Demandes</a>.
</div>
<a href="/static/img/Diagramme_Etat_Statut_Cooperateurs_Supercoop_220909.jpg" target=”_blank”>
<img class="status_info_image" src="/static/img/Diagramme_Etat_Statut_Cooperateurs_Supercoop_220909.jpg" alt="diagramme_etat_statut_cooperateurs"/>
</a>
</div>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment