Commit 730e964d by Etienne Freiss

Merge branch 'dev_cooperatic' into 2463-go-to-normal-validation-for-associated-member

parents 756ec12a 3ecb4014
Pipeline #1934 passed with stage
in 1 minute 28 seconds
......@@ -385,14 +385,24 @@ def delete_shift_registration(request):
is_connected_user = CagetteUser.are_credentials_ok(request)
if is_connected_user is True:
data = json.loads(request.body.decode())
shift_registration_id = int(data["shift_registration_id"])
member_id = int(data["member_id"])
m = CagetteShift()
res["res"] = m.cancel_shift([shift_registration_id])
shift_registration_id = int(data["shift_registration_id"])
shift_is_makeup = data["shift_is_makeup"]
# Note: 'upcoming_registration_count' in res.partner won't change because the _compute method
# in odoo counts canceled shift registrations.
m = CagetteShift()
res["cancel_shift"] = m.cancel_shift([shift_registration_id])
if shift_is_makeup is True:
fields = {
'name': "Admin BDM - Suppression d'un rattrapage",
'shift_id': False,
'type': data["member_shift_type"],
'partner_id': member_id,
'point_qty': 1
}
res["update_counter"] = m.update_counter_event(fields)
response = JsonResponse(res, safe=False)
else:
......
......@@ -133,6 +133,7 @@ class CagetteMember(models.Model):
fp = request.POST.get('fp') # fingerprint (prevent using stolen cookies)
if login and password:
api = OdooAPI()
login = login.strip()
cond = [['email', '=', login]]
if getattr(settings, 'ALLOW_NON_MEMBER_TO_CONNECT', False) is False:
cond.append('|')
......@@ -1146,7 +1147,7 @@ class CagetteMembers(models.Model):
def get_makeups_members():
api = OdooAPI()
cond = [['makeups_to_do','>', 0]]
fields = ['id', 'name', 'makeups_to_do','shift_type']
fields = ['id', 'name', 'display_std_points', 'display_ftop_points', 'shift_type', 'makeups_to_do']
res = api.search_read('res.partner', cond, fields)
return res
......@@ -1255,7 +1256,7 @@ class CagetteServices(models.Model):
).total_seconds() / 60 > default_acceptable_minutes_after_shift_begins
if with_members is True:
cond = [['id', 'in', s['registration_ids']], ['state', 'not in', ['cancel', 'waiting', 'draft']]]
fields = ['partner_id', 'shift_type', 'state', 'is_late']
fields = ['partner_id', 'shift_type', 'state', 'is_late', 'associate_registered']
members = api.search_read('shift.registration', cond, fields)
s['members'] = sorted(members, key=lambda x: x['partner_id'][0])
if len(s['members']) > 0:
......@@ -1264,22 +1265,27 @@ class CagetteServices(models.Model):
for m in s['members']:
mids.append(m['partner_id'][0])
cond = [['parent_id', 'in', mids]]
fields = ['parent_id', 'name']
fields = ['id', 'parent_id', 'name','barcode_base']
associated = api.search_read('res.partner', cond, fields)
if len(associated) > 0:
for m in s['members']:
for a in associated:
if int(a['parent_id'][0]) == int(m['partner_id'][0]):
m['partner_name'] = m['partner_id'][1]
m['partner_id'][1] += ' en binôme avec ' + a['name']
m['associate_name'] = str(a['barcode_base']) + ' - ' + a['name']
return services
@staticmethod
def registration_done(registration_id, overrided_date=""):
def registration_done(registration_id, overrided_date="", typeAction=""):
"""Equivalent to click present in presence form."""
api = OdooAPI()
f = {'state': 'done'}
if(typeAction != "normal" and typeAction != ""):
f['associate_registered'] = typeAction
late_mode = getattr(settings, 'ENTRANCE_WITH_LATE_MODE', False)
if late_mode is True:
# services = CagetteServices.get_services_at_time('14:28',0, with_members=False)
......@@ -1301,7 +1307,14 @@ class CagetteServices(models.Model):
return api.update('shift.registration', [int(registration_id)], f)
@staticmethod
def record_rattrapage(mid, sid, stid):
def reopen_registration(registration_id, overrided_date=""):
api = OdooAPI()
f = {'state': 'open'}
return api.update('shift.registration', [int(registration_id)], f)
@staticmethod
def record_rattrapage(mid, sid, stid, typeAction):
"""Add a shift registration for member mid.
(shift sid, shift ticket stid)
......@@ -1317,6 +1330,8 @@ class CagetteServices(models.Model):
"state": 'open'}
reg_id = api.create('shift.registration', fields)
f = {'state': 'done'}
if(typeAction != "normal" and typeAction != ""):
f['associate_registered'] = typeAction
return api.update('shift.registration', [int(reg_id)], f)
@staticmethod
......@@ -1332,6 +1347,20 @@ class CagetteServices(models.Model):
# let authorized people time to set presence for those who came in late
end_date = now - datetime.timedelta(hours=2)
api = OdooAPI()
# Let's start by adding an extra shift to associated member who came together
cond = [['date_begin', '>=', date_24h_before.isoformat()],
['date_begin', '<=', end_date.isoformat()],
['state', '=', 'done'], ['associate_registered', '=', 'both']]
fields = ['state', 'partner_id', 'date_begin']
res = api.search_read('shift.registration', cond, fields)
for r in res:
cond = [['id', '=', r['partner_id'][0]]]
fields = ['id','extra_shift_done']
res = api.search_read('res.partner', cond, fields)
f = {'extra_shift_done': res[0]['extra_shift_done'] + 1 }
api.update('res.partner', [r['partner_id'][0]], f)
absence_status = 'excused'
res_c = api.search_read('ir.config_parameter',
[['key', '=', 'lacagette_membership.absence_status']],
......
......@@ -38,6 +38,10 @@
padding-top: 0.755em;
}
.makeup_row {
background-color: #ffc854 !important;
}
/* Search membres area */
#search_member_area {
margin-top: 30px;
......
......@@ -44,8 +44,10 @@ h1 .member_name {font-weight: bold;}
.members_list {list-style: none;}
.members_list li {display:block;margin-bottom:5px;}
.members_list li.btn--inverse {background: #449d44; cursor:not-allowed; color: #FFF; }
.members_list li.btn--inverse {background: #449d44; color: #FFF; }
.members_list li.btn--inverse.not_connected {cursor:not-allowed}
.members_list li.btn--inverse.late {background-color: #de9b00; color: white}
.members_list li.btn--inverse.both {background-color: #0275d8 ; color: white}
#service_entry_success {font-size: x-large;}
#service_entry_success .explanations {margin: 25px 0; font-size: 18px;}
......@@ -64,7 +66,7 @@ h1 .member_name {font-weight: bold;}
#service_en_cours .info a {line-height: 24px; font-size:14px; margin-top:15px;}
.outside_list a {margin-left:15px;}
#rattrapage_1 .advice {margin-top:15px;}
.btn.present {background:#50C878;}
.btn.present {background:#50C878; color: white !important; font-weight: bold;}
.btn.return {background: #ff3333; color:#FFF !important; margin-top:25px;}
.msg-big {font-size: xx-large; background: #fff; padding:25px; text-align: center;}
......
......@@ -69,6 +69,19 @@ function display_makeups_members() {
title: "Nom"
},
{
data: "shift_type",
title: "Nb de points",
className: "dt-body-center",
width: "10%",
render: function (data, type, row) {
if (data == 'ftop') {
return row.display_ftop_points
} else if (data == 'standard') {
return row.display_std_points
}
}
},
{
data: "makeups_to_do",
title: "Nb rattrapages",
className: "dt-body-center",
......
......@@ -88,17 +88,29 @@ function display_member_shifts() {
"sLoadingRecords": "Chargement en cours...",
"sZeroRecords": "Aucun &eacute;l&eacute;ment &agrave; afficher",
"sEmptyTable": "Aucun futur service pour ce.tte membre"
}
},
createdRow: function(row, rdata) {
if (rdata.is_makeup === true) {
$(row).addClass("makeup_row");
$(row).prop('title', 'Ce service est un rattrapage');
}
},
});
$('#member_shifts_table').on('click', 'tbody td .delete_shift_registration', function () {
const row_data = member_shifts_table.row($(this).parents('tr')).data();
const shift_reg_id = row_data.id;
const shift_is_makeup = row_data.is_makeup;
let msg = `<p>Enlever la présence de <b>${member.name}</b> au service du <b>${row_data.shift_id[1]}</b> ?</p>`;
if (shift_is_makeup === true) {
msg += `<p><i class="fas fa-exclamation-triangle"></i> Ce service est un rattrapage. Le supprimer ajoutera un point au compteur de ce.tte membre.</p>`;
}
openModal(
`Enlever la présence de ${member.name} au service du ${row_data.shift_id[1]} ?`,
msg,
() => {
delete_shift_registration(shift_reg_id);
delete_shift_registration(shift_reg_id, shift_is_makeup);
},
"Confirmer",
false
......@@ -109,13 +121,16 @@ function display_member_shifts() {
/**
* Send request to delete shift registration
* @param {Int} shift_reg_id Id of the shift_registration to delete
* @param {Boolean} shift_is_makeup Is the shift a makeup?
*/
function delete_shift_registration(shift_reg_id) {
function delete_shift_registration(shift_reg_id, shift_is_makeup) {
openModal();
data = {
member_id: selected_member.id,
shift_registration_id: shift_reg_id
member_shift_type: selected_member.shift_type,
shift_registration_id: shift_reg_id,
shift_is_makeup: shift_is_makeup
};
$.ajax({
......
......@@ -588,8 +588,7 @@ $('#add_binome').click(function() {
delete current_coop.is_associated_people;
delete current_coop.shift_template;
}
}
else {
} else {
$('#associate_area').show();
$('.member_choice').removeClass('choice_active');
$('#existing_member_choice_action').hide();
......@@ -614,6 +613,12 @@ $('.member_choice').on('click', function() {
});
$('#shift_calendar').click(show_shift_calendar);
$('#search_member_input').keypress((event) => {
if (event.keyCode==13) {
event.preventDefault();
searchMembersForAssociate();
}
});
//get_latest_odoo_coop_bb();
update_self_records();
......@@ -688,45 +693,52 @@ function display_possible_members() {
}
/**
* Search for members to associate a new member with an old one.
*/
function searchMembersForAssociate() {
let search_str = $('#search_member_input').val();
if (search_str) {
$.ajax({
url: '/members/search/' + search_str+ "?search_type=members",
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();
}
}
$(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+ "?search_type=members",
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();
}
searchMembersForAssociate();
});
});
......@@ -31,12 +31,14 @@ var search_field = $('input[name="search_string"]');
var shift_title = $('#current_shift_title');
var shift_members = $('#current_shift_members');
var service_validation = $('#service_validation');
var associated_service_validation = $('#associated_service_validation');
var validation_last_call = 0;
var rattrapage_wanted = $('[data-next="rattrapage_1"]');
var webcam_is_attached = false;
var photo_advice = $('#photo_advice');
var photo_studio = $('#photo_studio');
var coop_info = $('.coop-info');
var service_data = null;
const missed_begin_msg = $('#missed_begin_msg').html();
......@@ -264,7 +266,7 @@ function get_simple_service_name(s) {
}
function move_service_validation_to(page) {
service_validation.find('.btn').data('stid', '0');
service_data.stid=0;
page.find('.validation_wrapper')
.append(service_validation.detach());
}
......@@ -284,11 +286,21 @@ function fill_service_entry(s) {
var li_class = "btn";
var li_data = "";
if (e.state == "done") {
if (e.state == "done" && coop_is_connected()) {
li_data = ' data-rid="'+e.id+'" data-mid="'+e.partner_id[0]+'"';
li_class += "--inverse";
if (e.is_late == true) {
li_class += " late";
}
if (e.associate_registered=='both') {
li_class += " both";
}
} else if (e.state == "done" && !coop_is_connected()) {
li_data = ' data-rid="'+e.id+'" data-mid="'+e.partner_id[0]+'"';
li_class += "--inverse not_connected";
if (e.is_late == true) {
li_class += " late";
}
} else {
li_data = ' data-rid="'+e.id+'" data-mid="'+e.partner_id[0]+'"';
}
......@@ -321,13 +333,29 @@ function clean_service_entry() {
function fill_service_validation(rid, coop_num_name, coop_id) {
var coop_name_elts = coop_num_name.split(' - ');
for (member of loaded_services[0].members) {
if (member.id ==rid) {
if (member.associate_name) {
pages.service_entry_validation.find('#service_validation').hide();
pages.service_entry_validation.find('#associated_service_validation').show();
pages.service_entry_validation.find('#associated_btn').text(member.associate_name);
pages.service_entry_validation.find('#partner_btn').text(member.partner_name);
} else {
pages.service_entry_validation.find('#associated_service_validation').hide();
pages.service_entry_validation.find('#service_validation').show();
}
}
}
service_data={
rid: rid,
sid: selected_service.id,
mid: coop_id};
pages.service_entry_validation.find('span.member_name').text(coop_name_elts[1]);
move_service_validation_to(pages.service_entry_validation);
service_validation.find('.btn')
.data('rid', rid)
.data('sid', selected_service.id)
.data('mid', coop_id);
}
function select_possible_service() {
......@@ -372,7 +400,6 @@ function get_service_entry_data() {
dataType : 'json'
})
.done(function(rData) {
//console.log(rData);
info_place.text('');
var page_title = pages.service_entry.find('h1');
......@@ -397,6 +424,7 @@ function get_service_entry_data() {
page_title.text('Quel est ton service ?');
} else {
loaded_services = rData.res;
fill_service_entry(rData.res[0]);
}
}
......@@ -443,22 +471,21 @@ function fill_service_entry_sucess(member) {
}
function record_service_presence() {
function record_service_presence(e) {
var d = new Date();
var elapsed_since_last_call = d.getTime() - validation_last_call;
if (elapsed_since_last_call > 10000) {
if (elapsed_since_last_call > 1000) {
loading2.show();
validation_last_call = d.getTime();
var clicked = service_validation.find('.btn');
var rid = clicked.data('rid');
var mid = clicked.data('mid');
var sid = clicked.data('sid');
var stid = clicked.data('stid');
var rid = service_data.rid;
var mid = service_data.mid;
var sid = service_data.sid;
var stid = service_data.stid;
post_form(
'/members/service_presence/',
{'mid': mid, 'rid': rid, 'sid': sid, 'stid' : stid},
{'mid': mid, 'rid': rid, 'sid': sid, 'stid' : stid, 'cancel': false, 'type': e.data.type},
function(err, rData) {
if (!err) {
var res = rData.res;
......@@ -480,6 +507,28 @@ function record_service_presence() {
}
}
function cancel_service_presence(mid, rid) {
var d = new Date();
var elapsed_since_last_call = d.getTime() - validation_last_call;
if (elapsed_since_last_call > 1000) {
loading2.show();
validation_last_call = d.getTime();
var sid = selected_service.id;
post_form(
'/members/service_presence/',
{'mid': mid, 'rid': rid, 'sid': sid, 'stid' : 0, 'cancel': true},
function(err) {
if (!err) {
get_service_entry_data();
}
loading2.hide();
}
);
}
}
function fill_rattrapage_2() {
pages.rattrapage_2.find('span.member_name').text(current_displayed_member.name);
var msg = "Bienvenue pour ton rattrapage !";
......@@ -494,13 +543,11 @@ function fill_rattrapage_2() {
msg = "Tu es en désincrit.e ... La situation doit être réglée avez le Bureau des Membres";
} else {
move_service_validation_to(pages.rattrapage_2);
service_validation.find('.btn')
.data('rid', 0)
.data('sid', selected_service.id)
.data('stid', shift_ticket_id)
.data('mid', current_displayed_member.id);
service_data = {
rid : 0,
sid : selected_service.id,
stid : shift_ticket_id,
mid : current_displayed_member.id};
}
pages.rattrapage_2.find('h2').text(msg);
......@@ -641,7 +688,10 @@ $('.btn[data-next]').click(function() {
});
service_validation.on("click", ".btn", record_service_presence);
service_validation.on("click", ".btn", {type:'normal'}, record_service_presence);
associated_service_validation.on("click", "#associated_btn", {type:'associate'}, record_service_presence);
associated_service_validation.on("click", "#partner_btn", {type:'partner'}, record_service_presence);
associated_service_validation.on("click", "#both_btn", {type:'both'}, record_service_presence);
shift_members.on("click", '.btn[data-rid]', function() {
var clicked = $(this);
......@@ -653,6 +703,16 @@ shift_members.on("click", '.btn[data-rid]', function() {
});
shift_members.on("click", '.btn--inverse', function() {
if (coop_is_connected()) {
var clicked = $(this);
var rid = clicked.data('rid');
var mid = clicked.data('mid');
cancel_service_presence(mid, rid);
}
});
pages.shopping_entry.on('css', function() {
photo_advice.hide();
photo_studio.hide();
......
......@@ -283,6 +283,9 @@ def record_service_presence(request):
mid = int(request.POST.get("mid", 0)) # member id
sid = int(request.POST.get("sid", 0)) # shift id
stid = int(request.POST.get("stid", 0)) # shift_ticket_id
cancel = request.POST.get("cancel") == 'true'
typeAction = str(request.POST.get("type"))
app_env = getattr(settings, 'APP_ENV', "prod")
if (rid > -1 and mid > 0):
overrided_date = ""
......@@ -292,28 +295,31 @@ def record_service_presence(request):
if o_date:
overrided_date = re.sub(r'(%20)',' ', o_date.group(1))
# rid = 0 => C'est un rattrapage, sur le service
if sid > 0 and stid > 0:
# Add member to service and take presence into account
res['rattrapage'] = CagetteServices.record_rattrapage(mid, sid, stid)
if res['rattrapage'] is True:
res['update'] = 'ok'
else:
if (CagetteServices.registration_done(rid, overrided_date) is True):
res['update'] = 'ok'
if(not cancel):
# rid = 0 => C'est un rattrapage, sur le service
if sid > 0 and stid > 0:
# Add member to service and take presence into account
res['rattrapage'] = CagetteServices.record_rattrapage(mid, sid, stid, typeAction)
if res['rattrapage'] is True:
res['update'] = 'ok'
else:
res['update'] = 'ko'
if res['update'] == 'ok':
members = CagetteMember.search('id', mid)
m = members[0]
for k in ['image_medium', 'barcode', 'barcode_base']:
del m[k]
next_shift = {}
if len(m['shifts']) > 0:
next_shift = m['shifts'][0]
del m['shifts']
m['next_shift'] = next_shift
res['member'] = m
if (CagetteServices.registration_done(rid, overrided_date, typeAction) is True):
res['update'] = 'ok'
else:
res['update'] = 'ko'
if res['update'] == 'ok':
members = CagetteMember.search('id', mid)
m = members[0]
for k in ['image_medium', 'barcode', 'barcode_base']:
del m[k]
next_shift = {}
if len(m['shifts']) > 0:
next_shift = m['shifts'][0]
del m['shifts']
m['next_shift'] = next_shift
res['member'] = m
else: CagetteServices.reopen_registration(rid, overrided_date)
except Exception as e:
res['error'] = str(e)
return JsonResponse({'res': res})
......
......@@ -64,14 +64,39 @@
}
}
.shift_line_container {
display: flex;
flex-direction: row;
align-items: center;
flex-wrap: wrap;
}
.shift_line_extra_actions {
display: flex;
justify-content: flex-start;
flex-wrap: nowrap;
}
@media screen and (max-width:768px) {
.shift_line_container {
flex-direction: column;
}
.shift_line_extra_actions {
width: 100%;
}
.affect_associate_registered {
margin: 0.5rem 0;
}
}
.selectable_shift_line {
min-width: 325px;
display: flex;
align-items: center;
margin-left: 15px;
margin: 0.75rem 0;
border-radius: 5px;
margin-right: 15px;
}
.selectable_shift_line .checkbox {
......@@ -85,11 +110,23 @@
.affect_associate_registered {
display: flex;
align-items: center;
margin-left: 15px;
margin: 0.75rem 0;
border-radius: 5px;
}
@media screen and (min-width:768px) {
.selectable_shift_line {
margin: 0 15px;
}
.affect_associate_registered {
margin-left: 15px;
}
}
.selectable_shift{
margin: 1rem 0;
}
.delete_registration_button {
justify-content: center;
align-items: center;
......@@ -125,9 +162,9 @@
#can_delete_future_registrations_area {
display: none;
align-self: center;
justify-content: center;
align-items: center;
margin: 0 1rem 1rem 1rem;
padding: 1rem 1.25rem;
}
#can_delete_future_registrations_area button {
......@@ -240,4 +277,14 @@ td{
#calendar_explaination_button {
max-width: 60%;
margin: 2rem auto 0.5rem auto;
}
/* -- Assign shift modal */
.modal_affect_shift_buttons {
margin: 1rem 0;
}
.assign_shift_button {
margin: 0.25rem;
}
\ No newline at end of file
/**
* Request a 6 month delay
*/
function request_delay() {
return new Promise((resolve) => {
let today = new Date();
const delay_start = today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate();
let today_plus_six_month = new Date();
today_plus_six_month.setMonth(today_plus_six_month.getMonth()+6);
const diff_time = Math.abs(today_plus_six_month - today);
const diff_days = Math.ceil(diff_time / (1000 * 60 * 60 * 24));
$.ajax({
type: 'POST',
url: "/shifts/request_delay",
dataType:"json",
data: {
verif_token: partner_data.verif_token,
idPartner: partner_data.partner_id,
start_date: delay_start,
duration: diff_days
},
success: function() {
partner_data.cooperative_state = 'delay';
partner_data.date_delay_stop = today_plus_six_month.getFullYear()+'-'+(today_plus_six_month.getMonth()+1)+'-'+today_plus_six_month.getDate();
resolve();
},
error: function(data) {
if (data.status == 403
&& typeof data.responseJSON != 'undefined'
&& data.responseJSON.message === "delays limit reached") {
closeModal();
let msg_template = $("#cant_have_delay_msg_template");
openModal(
msg_template.html(),
() => {
window.location =member_cant_have_delay_form_link;
},
"J'accède au formulaire",
true,
false
);
} else {
err = {msg: "erreur serveur lors de la création du délai", ctx: 'request_delay'};
if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
err.msg += ' : ' + data.responseJSON.error;
}
report_JS_error(err, 'members_space.home');
closeModal();
alert('Erreur lors de la création du délai.');
}
}
});
});
}
function init_my_shifts_tile() {
if (incoming_shifts.length === 0) {
$("#home_tile_my_services #home_incoming_services").text("Aucun service à venir...");
......
......@@ -217,7 +217,7 @@ function delete_shift_registration(shift_registration_id) {
* @param {string} shift_id
*/
function affect_shift(partner, shift_id) {
if (is_time_to('affect_shift')) {
if (is_time_to('affect_shift', 1000)) {
tData = 'idShiftRegistration=' + shift_id
+'&idPartner=' + partner_data.partner_id
+ '&affected_partner=' + partner
......@@ -309,7 +309,8 @@ function init_shifts_list() {
shift_line_template.find(".selectable_shift_line").removeClass("btn--primary");
shift_line_template.find(".selectable_shift_line").removeClass("btn");
shift_line_template.find(".selectable_shift_line").removeClass("btn--warning");
if (!can_exchange_shifts() && block_actions_for_attached_people === "True") {
if (!can_exchange_shifts()) {
shift_line_template.find(".selectable_shift_line").addClass("btn");
shift_line_template.find(".checkbox").prop("disabled", "disabled");
} else {
......@@ -327,11 +328,19 @@ function init_shifts_list() {
if (partner_data.associated_partner_id === "False" && partner_data.parent_id === "False") {
shift_line_template.find('.affect_associate_registered').hide();
} else {
if (!can_exchange_shifts()) {
shift_line_template.find('.affect_associate_registered').hide();
} else {
shift_line_template.find('.affect_associate_registered').show();
}
shift_line_template.find('.affect_associate_registered').closest(".shift_line_container")
.attr('id', 'shift_id_'+shift.id);
if (shift.associate_registered==="both") {
shift_line_template.find('.affect_associate_registered').text("Les deux");
shift_line_template.find('.affect_associate_registered').addClass('btn--success');
} else if (shift.associate_registered==="partner") {
shift_line_template.find('.affect_associate_registered').addClass('btn--success');
if (partner_data.associated_partner_id !== "False") {
shift_line_template.find('.affect_associate_registered').text(partner_data.name);
} else {
......@@ -339,6 +348,7 @@ function init_shifts_list() {
}
} else if (shift.associate_registered==="associate") {
shift_line_template.find('.affect_associate_registered').addClass('btn--success');
if (partner_data.associated_partner_id !== "False") {
shift_line_template.find('.affect_associate_registered').text(partner_data.associated_partner_name);
} else {
......@@ -346,6 +356,7 @@ function init_shifts_list() {
}
} else {
shift_line_template.find('.affect_associate_registered').text("A déterminer");
shift_line_template.find('.affect_associate_registered').addClass('btn--danger');
}
}
......@@ -354,13 +365,15 @@ function init_shifts_list() {
if (shift_line_template.find(".delete_registration_button").length === 0) {
let delete_reg_button_template = $("#delete_registration_button_template");
shift_line_template.find(".shift_line_container").append(delete_reg_button_template.html());
shift_line_template.find(".shift_line_extra_actions").append(delete_reg_button_template.html());
}
} else {
shift_line_template.find(".delete_registration_button").remove();
}
$("#shifts_list").append(shift_line_template.html());
shift_line_template.find('.affect_associate_registered').removeClass('btn--danger');
shift_line_template.find('.affect_associate_registered').removeClass('btn--success');
}
$(".selectable_shift_line").on("click", function(e) {
......@@ -402,8 +415,8 @@ function init_shifts_list() {
modal_template.find("#shift_associate").text(partner_data.associated_partner_name);
} else {
modal_template.find("#shift_partner").text(partner_data.name);
modal_template.find("#shift_associate").text(partner_data.parent_name);
modal_template.find("#shift_partner").text(partner_data.parent_name);
modal_template.find("#shift_associate").text(partner_data.name);
}
openModal(
......@@ -470,7 +483,7 @@ function init_calendar_page() {
if (partner_data.extra_shift_done > 0) {
$(".extra_shift_done").text(partner_data.extra_shift_done);
$("#can_delete_future_registrations_area").show();
$("#can_delete_future_registrations_area").css('display', 'flex');
$("#offer_extra_shift").on("click", () => {
openModal(
......@@ -763,8 +776,7 @@ function init_shifts_exchange() {
$(this).removeClass('active');
});
});
} else if (
partner_data.comite === "True") {
} else if (partner_data.comite === "True") {
let msg_template = $("#comite_template");
$(".comite_content_msg").html(msg_template.html());
......
......@@ -131,6 +131,70 @@ function update_content() {
/* - Shifts */
/**
* Request a 6 month delay
*/
function request_delay() {
return new Promise((resolve) => {
let today = new Date();
const delay_start = today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate();
let today_plus_six_month = new Date();
today_plus_six_month.setMonth(today_plus_six_month.getMonth()+6);
const diff_time = Math.abs(today_plus_six_month - today);
const diff_days = Math.ceil(diff_time / (1000 * 60 * 60 * 24));
$.ajax({
type: 'POST',
url: "/shifts/request_delay",
dataType:"json",
data: {
verif_token: (partner_data.is_associated_people === "True") ? partner_data.parent_verif_token : partner_data.verif_token,
idPartner: partner_data.concerned_partner_id,
start_date: delay_start,
duration: diff_days
},
success: function() {
partner_data.cooperative_state = 'delay';
partner_data.date_delay_stop = today_plus_six_month.getFullYear()+'-'+(today_plus_six_month.getMonth()+1)+'-'+today_plus_six_month.getDate();
resolve();
},
error: function(data) {
if (data.status == 403
&& typeof data.responseJSON != 'undefined'
&& data.responseJSON.message === "delays limit reached") {
closeModal();
let msg_template = $("#cant_have_delay_msg_template");
openModal(
msg_template.html(),
() => {
window.location =member_cant_have_delay_form_link;
},
"J'accède au formulaire",
true,
false
);
} else {
err = {msg: "erreur serveur lors de la création du délai", ctx: 'request_delay'};
if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
err.msg += ' : ' + data.responseJSON.error;
}
report_JS_error(err, 'members_space.home');
closeModal();
alert('Erreur lors de la création du délai.');
}
}
});
});
}
/**
* Prepare a shift line to insert into the DOM.
* Is used in: Home - My Shifts tile ; My Shifts - Incoming shifts section
*
......@@ -200,7 +264,6 @@ function init_my_info_data() {
if (
partner_data.makeups_to_do > 0
&& partner_data.is_associated_people === "False"
&& partner_data.cooperative_state !== 'unsubscribed'
) {
$(".choose_makeups").show();
......@@ -235,8 +298,6 @@ function init_my_info_data() {
}
$(document).ready(function() {
// TODO essayer de ne charger les js que au besoin
$.ajaxSetup({ headers: { "X-CSRFToken": getCookie('csrftoken') } });
// If partner is associated (attached), display the pair's main partner shift data
......@@ -250,7 +311,6 @@ $(document).ready(function() {
// For associated people, their parent name is attached in their display name
let partner_name_split = partner_data.name.split(', ');
partner_data.name = partner_name_split[partner_name_split.length - 1];
base_location = (app_env === 'dev') ? '/members_space/' : '/';
......
......@@ -99,10 +99,14 @@ def index(request, exception=None):
partnerData["parent_id"] = partnerData["parent_id"][0]
md5_calc = hashlib.md5(partnerData['parent_create_date'].encode('utf-8')).hexdigest()
partnerData['parent_verif_token'] = md5_calc
partnerData['makeups_to_do'] = partnerData['parent_makeups_to_do']
partnerData['date_delay_stop'] = partnerData['parent_date_delay_stop']
partnerData['can_have_delay'] = cs.member_can_have_delay(int(partnerData["parent_id"]))
partnerData['extra_shift_done'] = partnerData["parent_extra_shift_done"]
else:
partnerData["parent_name"] = False
partnerData['can_have_delay'] = cs.member_can_have_delay(int(partner_id))
# look for associated partner for parents
cm = CagetteMember(partner_id)
......@@ -114,8 +118,6 @@ def index(request, exception=None):
if (associated_partner is not None and partnerData["associated_partner_name"].find(str(associated_partner["barcode_base"])) == -1):
partnerData["associated_partner_name"] = str(associated_partner["barcode_base"]) + ' - ' + partnerData["associated_partner_name"]
partnerData['can_have_delay'] = cs.member_can_have_delay(int(partner_id))
m = CagetteMembersSpace()
context['show_faq'] = getattr(settings, 'MEMBERS_SPACE_FAQ_TEMPLATE', 'members_space/faq.html')
partnerData["comite"] = m.is_comite(partner_id)
......
......@@ -7,7 +7,8 @@
.red {color:#FF0000;}
.b_red, .b_less_than_25pc {background:#ff3333 !important;}
.loading {background-image: url("/static/img/ajax-loader.gif"); background-repeat:no-repeat;}
.loading2 {display: none;}
.loading2 {display: none; position:absolute; top:-20px;}
.loading2-container {position:relative;}
body {background: #fff; margin:5px;}
a, a:active, a:focus,
......
......@@ -45,10 +45,12 @@ class CagetteShift(models.Model):
partnerData = partnerData[0]
if partnerData['is_associated_people']:
cond = [['id', '=', partnerData['parent_id'][0]]]
fields = ['create_date', 'extra_shift_done']
fields = ['create_date', 'makeups_to_do', 'date_delay_stop', 'extra_shift_done']
parentData = self.o_api.search_read('res.partner', cond, fields, 1)
if parentData:
partnerData['parent_create_date'] = parentData[0]['create_date']
partnerData['parent_makeups_to_do'] = parentData[0]['makeups_to_do']
partnerData['parent_date_delay_stop'] = parentData[0]['date_delay_stop']
partnerData['parent_extra_shift_done'] = parentData[0]['extra_shift_done']
if partnerData['shift_type'] == 'standard':
......@@ -367,4 +369,8 @@ class CagetteShift(models.Model):
def member_can_have_delay(self, partner_id):
""" Can a member have a delay? """
return self.o_api.execute('res.partner', 'can_have_extension', [partner_id])
\ No newline at end of file
return self.o_api.execute('res.partner', 'can_have_extension', [partner_id])
def update_counter_event(self, fields):
""" Add/remove points """
return self.o_api.create('shift.counter.event', fields)
\ No newline at end of file
......@@ -138,9 +138,13 @@
</section>
</section>
<section class="grid-6 has-gutter" id="service_entry">
<div class="col-6 row-2">
<div class="col-2 row-2">
<a class="btn btn--primary" data-next="first_page" >Retour accueil</a>
</div>
<div class="col-2 row-2"></div>
<div class="col-2 row-2 login_area">
{% include "common/conn_admin.html" %}
</div>
<div class="col-1"></div>
<div class="col-4">
<h1 class="col-4 txtcenter">Qui es-tu ?</h1>
......@@ -178,9 +182,23 @@
<section id="service_validation" class="col-6 grid-6 has-gutter">
<div class="col-2"></div>
<a class="col-2 btn present">{{CONFIRME_PRESENT_BTN|safe}}</a>
<span class="loading2"><img width="75" src="/static/img/Pedro_luis_romani_ruiz.gif" alt="Chargement en cours...." /></span>
<div class="col-2"></div>
<div class="col-2 loading2-container">
<span class="loading2"><img width="75" src="/static/img/Pedro_luis_romani_ruiz.gif" alt="Chargement en cours...." /></span>
</div>
</section>
<div id="associated_service_validation">
<p class="col-6 txtcenter">Qui est présent à ce service ?</p>
<section class="col-6 grid-5 has-gutter">
<div class="col-1"></div>
<a id="associated_btn" class=" btn present">Membre</a>
<a id="partner_btn" class=" btn present">Associé</a>
<a id="both_btn" class=" btn present">Les deux</a>
<div class="col-1 loading2-container">
<span class="loading2"><img width="75" src="/static/img/Pedro_luis_romani_ruiz.gif" alt="Chargement en cours...." /></span>
</div>
</section>
</div>
</div>
<div class="col-2"></div>
<a class="btn col-2 return" data-next="service_entry">Retour</a>
......
......@@ -36,14 +36,18 @@
</div>
<div id="selectable_shift_line_template">
<div class="d-flex shift_line_container">
<div class="d-flex shift_line_container selectable_shift">
<div class="selectable_shift_line btn--primary">
<input type="checkbox" class="checkbox">
<div class="selectable_shift_line_text">
<span class="shift_line_date"></span> - <span class="shift_line_time"></span>
</div>
</div>
<div class="affect_associate_registered button--warning"></div>
<div class="shift_line_extra_actions">
<div class="affect_associate_registered">
</div>
</div>
</div>
</div>
......@@ -53,12 +57,14 @@
<div id="modal_affect_shift">
<div>Qui sera présent.e ?</div>
<div id="shift_partner" class="btn--primary">
</div>
<div id="shift_associate" class=" btn--primary">
</div>
<div id="shift_both" class=" btn--primary">
Les deux
<div class="modal_affect_shift_buttons">
<div id="shift_partner" class="btn--primary assign_shift_button">
</div>
<div id="shift_associate" class=" btn--primary assign_shift_button">
</div>
<div id="shift_both" class=" btn--primary assign_shift_button">
Les deux
</div>
</div>
</div>
......
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