Commit 41c352f2 by François C.

Merge branch '2253-new-binome' into 'dev_cooperatic'

2253 new binome

See merge request !130
parents 5cfdcae6 cdea4b50
Pipeline #1877 passed with stage
in 1 minute 28 seconds
......@@ -13,6 +13,7 @@ import pytz
import locale
import re
import dateutil.parser
from datetime import date
......@@ -350,6 +351,23 @@ class CagetteMember(models.Model):
return answer
@staticmethod
def is_associated(id_parent):
api = OdooAPI()
cond = [['parent_id', '=', int(id_parent)]]
fields = ['id','name','parent_id','birthdate']
res = api.search_read('res.partner', cond, fields, 10, 0, 'id DESC')
already_have_adult_associated = False
for partner in res:
birthdate = partner['birthdate']
if(birthdate):
today = date.today()
date1 = datetime.datetime.strptime(birthdate, "%Y-%m-%d")
age = today.year - date1.year - ((today.month, today.day) < (date1.month, date1.day))
if age > 17 :
already_have_adult_associated = True
return already_have_adult_associated
@staticmethod
def finalize_coop_creation(post_data):
""" Update coop data. """
res = {}
......@@ -505,7 +523,30 @@ class CagetteMember(models.Model):
m.create_capital_subscription_invoice(post_data['shares_euros'], today)
res['bc'] = m.generate_base_and_barcode(post_data)
# Create shift suscription
# if the new member is associated with an already existing member
# then we put the state in "associated" and we create the "associated" member
if 'is_associated_people' in post_data and 'parent_id' in post_data :
fields = {}
fields['cooperative_state'] = 'associated'
api.update('res.partner', [partner_id], fields)
associated_member = {
'email': post_data['_id'],
'name': name,
'birthdate': birthdate,
'sex': sex,
'street': post_data['address'],
'zip': post_data['zip'],
'city': post_data['city'],
'phone': format_phone_number(post_data['mobile']), # Because list view default show Phone and people mainly gives mobile
'barcode_rule_id': settings.COOP_BARCODE_RULE_ID,
'parent_id' : post_data['parent_id'],
'is_associated_people': True
}
associated_member_id = api.create('res.partner', associated_member)
# If it's an new associated member with a new partner. Link will be made by the user in BDM/admin
# We add the associated member to the "associate" shift template so we can find them in Odoo
elif 'is_associated_people' not in post_data or 'is_associated_people' in post_data and 'parent_id' not in post_data:
# Create shift suscription if is not associated
shift_template = json.loads(post_data['shift_template'])
shift_t_id = shift_template['data']['id']
stype = shift_template['data']['type']
......
......@@ -26,3 +26,51 @@
#mail_generation {position:absolute; bottom:30px;}
#sex {padding: 0;}
#existing_partner{
padding-right: 15px;
width: 45%;
}
#new_partner{
padding-left: 15px;
width: 45%;
}
#add_binome{
cursor: pointer;
text-decoration: underline;
font-weight: bold;
}
#existing_member_choice, #new_member_choice{
border: 1px solid black;
width: 40%;
cursor: pointer;
text-align: center;
max-width: 400px;
background-color: #e7e9ed;
color: black;
padding: 1rem 1.5rem;
}
#existing_member_choice:hover, #new_member_choice:hover{
background-color: #ccc;
}
.choice_active{
background-color: #0275d8 !important;
color: white !important;
}
#existing_member_choice{
margin-right: 15px;
}
.choice_button_area{
margin-bottom: 10px;
}
#associate_area{
margin-bottom: 15px;
}
\ No newline at end of file
......@@ -17,8 +17,9 @@ var latest_odoo_coop_bb = null,
subs_cap = $('#subs_cap'),
m_barcode = $('#m_barcode'),
sex = $('#sex'),
self_records = [],
selected_associate=null,
associated_old_choice= null,
choose_shift_msg = "Il est nécessaire de choisir un créneau (ABCD ou Volant) avant de pouvoir faire quoique ce soit d'autre.\nUne personne qui souhaite être rattachée au compte d'un autre membre dans le cadre d'un binôme doit choisir le créneau volant.";
......@@ -106,6 +107,11 @@ function reset_sex_radios() {
}
function create_new_coop() {
selected_associate= null;
$('#associate_area').hide();
$('.chosen_associate').html("");
$('.chosen_associate_area').hide();
$('.member_choice').removeClass('choice_active');
local_in_process = getLocalInProcess();
if (getLocalInProcess().length > 0) {
empty_waiting_local_processes();
......@@ -129,7 +135,6 @@ function create_new_coop() {
alert(choose_shift_msg);
}
}
}
function swipe_to_shift_choice() {
ncoop_view.hide();
......@@ -167,6 +172,30 @@ function _really_save_new_coop(email, fname, lname, cap, pm, cn, bc, msex) {
coop.payment_meaning = pm;
coop.checks_nb = cn;
coop.fingerprint = fingerprint;
if (associated_old_choice == 'existing_member_choice') {
if (selected_associate!=null) {
coop.is_associated_people = true;
coop.parent_id=selected_associate.id;
coop.parent_name=selected_associate.barcode_base + ' - '+ selected_associate.name;
coop.shift_template = shift_templates[ASSOCIATE_MEMBER_SHIFT];
}
} else if (associated_old_choice == 'new_member_choice' && $('#new_member_input').val()!='') {
coop.is_associated_people = true;
coop.parent_name=$('#new_member_input').val();
delete coop.parent_id;
coop.shift_template = shift_templates[ASSOCIATE_MEMBER_SHIFT];
} else {
delete coop.is_associated_people;
delete coop.parent_id;
delete coop.parent_name;
}
selected_associate=null;
$('#new_member_input').val('');
$('#associate_area').hide();
$('.chosen_associate_area').hide();
$('.chosen_associate').html("");
associated_old_choice= null;
if (m_barcode.length > 0) coop.m_barcode = bc;
if (sex.length > 0) coop.sex = msex;
coop.validation_state = "to_fill";
......@@ -174,11 +203,13 @@ function _really_save_new_coop(email, fname, lname, cap, pm, cn, bc, msex) {
if (!err) {
coop._rev = result.rev;
current_coop = coop;
if (typeof coop.shift_template != "undefined") {
if (typeof coop.shift_template != "undefined" && coop.shift_template.data.id != ASSOCIATE_MEMBER_SHIFT) {
openModal(
'Voulez-vous modifier le créneau choisi ?', swipe_to_shift_choice, 'oui',
false, true, show_coop_list
);
} else if (coop.is_associated_people && typeof coop.shift_template != "undefined" && coop.shift_template.data.id == ASSOCIATE_MEMBER_SHIFT) {
ncoop_view.hide();
} else {
swipe_to_shift_choice();
}
......@@ -226,8 +257,25 @@ function store_new_coop(event) {
if (typeof(rData.answer) == 'boolean' && rData.answer == true) {
errors.push("Il y a déjà un enregistrement Odoo avec cette adresse mail !");
}
if (selected_associate!=null) {
$.ajax({url : '/members/is_associated/' + selected_associate.id,
dataType :'json'
}).done(function(rData) {
if (typeof(rData.answer) == 'boolean' && rData.answer == true) {
errors.push("Ce membre à déjà un Binôme majeur");
}
if (errors.length == 0) {
_really_save_new_coop(
email, fname, lname,
subs_cap.val(), payment_meaning.val(), ch_qty.val(), bc, msex
);
} else {
alert(errors.join("\n"));
}
});
} else {
if (errors.length == 0) {
_really_save_new_coop(
email, fname, lname,
......@@ -237,6 +285,8 @@ function store_new_coop(event) {
} else {
alert(errors.join("\n"));
}
}
});
}
......@@ -273,6 +323,29 @@ function modify_current_coop() {
} else {
ch_qty.hide();
}
if (current_coop.is_associated_people) {
$('.member_choice').removeClass('choice_active');
$('#associate_area').show();
if (current_coop.parent_id) {
$('#existing_member_choice_action').show();
$('#new_member_choice_action').hide();
$('#existing_member_choice').addClass('choice_active');
var member_button = '<div>' + current_coop.parent_name + '</div>';
$('.chosen_associate').html(member_button);
$('.chosen_associate_area').show();
associated_old_choice = 'existing_member_choice';
} else {
$('#new_member_choice_action').show();
$('#existing_member_choice_action').hide();
$('#new_member_choice').addClass('choice_active');
$('#new_member_input').val(current_coop.parent_name);
$('.chosen_associate').html('');
$('.chosen_associate_area').hide();
associated_old_choice = 'new_member_choice';
}
}
subs_cap.val(current_coop.shares_euros);
if (m_barcode.length > 0) m_barcode.val(current_coop.m_barcode);
if (sex.length > 0) {
......@@ -497,6 +570,41 @@ $('#coop_create').submit(store_new_coop);
$('#generate_email').click(generate_email);
$('#odoo_user_connect').click();
$('#add_binome').click(function() {
if ($('#associate_area').is(':visible')) {
$('#associate_area').hide();
associated_old_choice = null;
$('#new_member_input').val('');
if (current_coop !=null) {
delete current_coop.parent_name;
delete current_coop.parent_id;
delete current_coop.is_associated_people;
delete current_coop.shift_template;
}
}
else {
$('#associate_area').show();
$('.member_choice').removeClass('choice_active');
$('#existing_member_choice_action').hide();
$('#new_member_choice_action').hide();
associated_old_choice = null;
}
});
$('.member_choice').on('click', function() {
if (associated_old_choice !=null && associated_old_choice!=$(this).attr('id')) {
$('#'+$(this).attr('id')+'_action').show();
$('#'+associated_old_choice+'_action').hide();
$('#'+associated_old_choice).removeClass('choice_active');
} else if (associated_old_choice ==null) {
$('#'+$(this).attr('id')+'_action').show();
}
associated_old_choice=$(this).attr('id');
$(this).addClass('choice_active');
});
$('#shift_calendar').click(show_shift_calendar);
......@@ -516,3 +624,102 @@ payment_meaning.change(function() {
window.addEventListener("beforeunload", keep_in_process_work);
empty_waiting_local_processes();
/**
* Display the members from the search result
*/
function display_possible_members() {
$('.search_member_results_area').show();
$('.search_member_results').empty();
$('.btn_possible_member').off();
$('.chosen_associate').html("");
$('.chosen_associate_area').hide();
let no_result = true;
if (members_search_results.length > 0) {
for (member of members_search_results) {
$(".search_results_text").show();
no_result = false;
// Display results (possible members) as buttons
var member_button = '<button class="btn--success btn_possible_member" member_id="'
+ member.id + '">'
+ member.barcode_base + ' - ' + member.name
+ '</button>';
$('.search_member_results').append(member_button);
}
// Set action on member button click
$('.btn_possible_member').on('click', function() {
for (member of members_search_results) {
if (member.id == $(this).attr('member_id')) {
selected_associate = member;
var member_button = '<div member_id="' + member.id + '">' + member.barcode_base + ' - ' + member.name + '</button>';
$('.chosen_associate').html(member_button);
$('.chosen_associate_area').show();
$('.search_member_results').empty();
$('.search_member_results_area').hide();
$('#search_member_input').val('');
break;
}
}
});
}
if (no_result === true) {
$(".search_results_text").hide();
$('.search_member_results').html(`<p>
<i>Aucun résultat ! Vérifiez votre recherche, ou si le.la membre n'est pas déjà dans le tableau...</i>
</p>`);
}
}
$(document).ready(function() {
retrieve_and_draw_shift_tempates();
// Set action to search for the member
$('#search_member_button').on('click', function() {
let search_str = $('#search_member_input').val();
if (search_str) {
$.ajax({
url: '/members/search/' + search_str,
dataType : 'json',
success: function(data) {
members_search_results = [];
for (member of data.res) {
if (member.is_member || member.is_associated_people) {
members_search_results.push(member);
}
}
display_possible_members();
},
error: function() {
err = {
msg: "erreur serveur lors de la recherche de membres",
ctx: 'search_member_form.search_members'
};
report_JS_error(err, 'members.admin');
$.notify("Erreur lors de la recherche de membre, il faut ré-essayer plus tard...", {
globalPosition:"top right",
className: "error"
});
}
});
}
else {
members_search_results = [];
display_possible_members();
}
});
});
......@@ -32,6 +32,15 @@ function display_current_coop_form() {
let street2_input = form.find('[name="street2"]'),
phone_input = form.find('[name="phone"]');
if (current_coop.parent_name) {
$('#associated_member').show();
if (current_coop.parent_id)
$('#associated_member_name').text(current_coop.parent_name);
else $('#associated_member_name').text(current_coop.parent_name + " ATTENTION à faire manuellement");
} else {
$('#associated_member').hide();
}
chgt_shift_btn.hide();
chgt_shift_btn.off('click', open_shift_choice);
form.find('[name="firstname"]').val(current_coop.firstname);
......
......@@ -31,6 +31,7 @@ urlpatterns = [
url(r'^latest_coop_id/$', views.latest_coop_id),
url(r'^get/([0-9]+)$', views.get),
url(r'^exists/([a-zA-Z0-9_\-\.\+@]+)$', views.exists),
url(r'^is_associated/([0-9]+)$', views.is_associated),
url(r'^get_couchdb_odoo_markers/(.+)$', views.get_couchdb_odoo_markers),
url(r'^menu/$', views.menu),
url(r'^verify_final_state$', views.verify_final_state),
......
......@@ -63,6 +63,10 @@ def exists(request, mail):
answer = CagetteMember.exists(mail)
return JsonResponse({'answer': answer})
def is_associated(request, id_parent):
answer = CagetteMember.is_associated(id_parent)
return JsonResponse({'answer': answer})
def getmemberimage(request, id):
m = CagetteMember(id)
call_res = m.get_image()
......@@ -97,7 +101,9 @@ def inscriptions(request, type=1):
'POUCHDB_VERSION': getattr(settings, 'POUCHDB_VERSION', ''),
'max_chq_nb': getattr(settings, 'MAX_CHQ_NB', 12),
'show_ftop_button': getattr(settings, 'SHOW_FTOP_BUTTON', True),
'db': settings.COUCHDB['dbs']['member']}
'db': settings.COUCHDB['dbs']['member'],
'ASSOCIATE_MEMBER_SHIFT' : getattr(settings, 'ASSOCIATE_MEMBER_SHIFT', '')
}
response = HttpResponse(template.render(context, request))
return response
......
......@@ -36,7 +36,7 @@ function add_or_change_shift(new_shift_id) {
+'&idPartner=' + partner_data.partner_id
+ '&shift_type=' + partner_data.shift_type
+ '&verif_token=' + partner_data.verif_token;
} else if(partner_data.is_associated_people === "True" && block_actions_for_attached_people === "False") {
} else if (partner_data.is_associated_people === "True" && block_actions_for_attached_people === "False") {
tData = 'idNewShift=' + new_shift_id
+'&idPartner=' + partner_data.parent_id
+ '&shift_type=' + partner_data.shift_type
......
......@@ -129,6 +129,10 @@
La Cagette use False to implement custom rules
- ASSOCIATE_MEMBER_SHIFT = ''
Id number of the associate shift template
### Scales and labels files generation
- DAV_PATH = '/data/dav/cagette'
......
......@@ -35,14 +35,15 @@ function get_shift_name(s_data) {
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) {
if (s_data.type == 2 && typeof manage_ftop != "undefined" && manage_ftop == true && s_data.id != ASSOCIATE_MEMBER_SHIFT) {
shift_name = 'Volant';
} else if(s_data.id == ASSOCIATE_MEMBER_SHIFT) {
shift_name = 'Binôme';
} else {
shift_name += s_data.day + ' - ' + s_data.begin;
shift_name += ' - ' + s_data.place;
}
}
return shift_name;
}
......
......@@ -37,7 +37,7 @@
<section class="center" id="new_coop">
<div class="grid-1">
<div class="item-center">
<div class="">
<h2 class="title">
NOUVEAU MEMBRE
</h2>
......@@ -65,14 +65,55 @@
<input type="number" min="1" placeholder="Nb de chèques" name="ch_qty" id="ch_qty" style="display:none;"/>
</p>
{% if input_barcode %}
<p>
<input type="text" name="m_barcode" id="m_barcode" maxlength="13" size="13" placeholder="Code barre" autocomplete="off" required/>
</p>
{% endif %}
{% if ASSOCIATE_MEMBER_SHIFT %}
<p id="add_binome" >+ Binomes (facultatif)</p>
<div id="associate_area" style="display:none;">
<div class="choice_button_area d-flex" >
<div id="existing_member_choice" class="member_choice">
A mettre en binome avec un.e membre existant.e
</div>
<div id="new_member_choice" class="member_choice">
A mettre en binome avec un.e nouveau membre
</div>
</div>
<div id="existing_member_choice_action" style="display:none;">
<input type="text" id="search_member_input" value="" placeholder="Nom ou numéro du coop..." >
<div class="btn--primary" id="search_member_button">Recherche</div>
<div class="search_member_results_area" style="display:none;">
<div class="search_results_text">
<p><i>Choisissez parmi les membres trouvés :</i></p>
</div>
<div class="search_member_results"></div>
</div>
<div class="chosen_associate_area" style="display:none;">
<div >
<p><i>Binôme choisit : </i></p>
</div>
<div class="chosen_associate"></div>
</div>
</div>
<div id="new_member_choice_action" style="display:none;">
<div >
<div>
<input type="text" id="new_member_input" value="" placeholder="Nom du membre" >
</div>
</div>
</div>
</div>
{% endif %}
<div>
<button class="btn--primary">Valider</button>
</form>
</div>
</form>
<div id="mail_generation">
(*) L'adresse mail étant obligatoire, si le nouveau membre n'en a pas, veuillez en créer une en cliquant sur le bouton suivant : <a class="btn--info" id="generate_email">+</a>
</div>
......@@ -119,6 +160,7 @@
var couchdb_dbname = '{{db}}';
var couchdb_server = '{{couchdb_server}}' + couchdb_dbname;
var dbc = new PouchDB(couchdb_dbname);
var ASSOCIATE_MEMBER_SHIFT = '{{ASSOCIATE_MEMBER_SHIFT}}';
var sync = PouchDB.sync(couchdb_dbname, couchdb_server, {
live: true,
retry: true,
......
......@@ -60,6 +60,9 @@
<input type="text" name="m_barcode" id="m_barcode" disabled/>
</p>
{% endif %}
<div id="associated_member">
En binôme avec : <span id ="associated_member_name"></span>
</div>
</div>
<p class="buttons">
<button class="btn--success" name="valider">Tout est bon</button>
......
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