Commit 326486b1 by Félicie

Merge branch '3817-bdm-increase-delay' into 'dev_cooperatic'

3817 bdm increase delay

See merge request !207
parents 0d624d73 70afef87
Pipeline #2435 passed with stage
in 1 minute 24 seconds
...@@ -8,7 +8,7 @@ from members.models import CagetteMember ...@@ -8,7 +8,7 @@ from members.models import CagetteMember
from shifts.models import CagetteServices from shifts.models import CagetteServices
from shifts.models import CagetteShift from shifts.models import CagetteShift
from outils.common import MConfig from outils.common import MConfig
from datetime import datetime from datetime import datetime, date
default_msettings = {'msg_accueil': {'title': 'Message borne accueil', default_msettings = {'msg_accueil': {'title': 'Message borne accueil',
'type': 'textarea', 'type': 'textarea',
...@@ -415,6 +415,66 @@ def update_members_makeups(request): ...@@ -415,6 +415,66 @@ def update_members_makeups(request):
response = JsonResponse(res, status=403) response = JsonResponse(res, status=403)
return response return response
def regenerate_member_delay(request):
""" From BDM admin, close existing extension if exists & recreate for 6 months """
res = {}
is_connected_user = CagetteUser.are_credentials_ok(request)
if is_connected_user is True:
raw_data = json.loads(request.body.decode())
# Close extension if has one
member_id = int(raw_data["member_id"])
cm = CagetteMember(member_id)
cm.close_extension()
# Recreate starting now
cs = CagetteShift()
data = {
"idPartner": member_id,
"start_date": date.today().isoformat()
}
duration = raw_data["duration"]
ext_name = "Délai étendue depuis l'admin BDM"
res["create_delay"] = cs.create_delay(data=data, duration=duration, ext_name=ext_name)
if (res["create_delay"]):
try:
# Add 0 pt to counter so odoo updates member status
data = {
'name': "Forcer l'entrée en délai",
'shift_id': False,
'type': "standard",
'partner_id': member_id,
'point_qty': 0
}
cm.update_member_points(data)
data = {
'name': "Forcer l'entrée en délai",
'shift_id': False,
'type': "ftop",
'partner_id': member_id,
'point_qty': 0
}
cm.update_member_points(data)
res["force_entry_delay"] = True
except Exception as e:
print(str(e))
else:
coop_logger.error("regenerate_member_delay: %s, %s", str(res["create_delay"]), str(data))
return HttpResponseServerError()
res["member_data"] = CagetteMembers.get_makeups_members([member_id])[0]
response = JsonResponse(res, safe=False)
else:
res["message"] = "Unauthorized"
response = JsonResponse(res, status=403)
return response
# --- Gestion des créneaux # --- Gestion des créneaux
......
...@@ -1007,14 +1007,7 @@ class CagetteMember(models.Model): ...@@ -1007,14 +1007,7 @@ class CagetteMember(models.Model):
if changing_shift is False: if changing_shift is False:
# Close extensions if just unsubscribing, else keep it # Close extensions if just unsubscribing, else keep it
c = [['partner_id', '=', self.id], ['date_start', '<=', now], ['date_stop', '>=', now]] res["close_extensions"] = self.close_extension()
f = ['id']
res_ids = self.o_api.search_read("shift.extension", c, f)
ids = [d['id'] for d in res_ids]
if ids:
f = {'date_stop': now}
res["close_extensions"] = self.o_api.update('shift.extension', ids, f)
return res return res
...@@ -1035,6 +1028,20 @@ class CagetteMember(models.Model): ...@@ -1035,6 +1028,20 @@ class CagetteMember(models.Model):
return res return res
def close_extension(self):
now = datetime.datetime.now().isoformat()
c = [['partner_id', '=', self.id], ['date_start', '<=', now], ['date_stop', '>=', now]]
f = ['id']
res_ids = self.o_api.search_read("shift.extension", c, f)
ids = [d['id'] for d in res_ids]
if ids:
f = {'date_stop': now}
return self.o_api.update('shift.extension', ids, f)
else:
return False
class CagetteMembers(models.Model): class CagetteMembers(models.Model):
"""Class to manage operations on all members or part of them.""" """Class to manage operations on all members or part of them."""
...@@ -1257,10 +1264,14 @@ class CagetteMembers(models.Model): ...@@ -1257,10 +1264,14 @@ class CagetteMembers(models.Model):
return res return res
@staticmethod @staticmethod
def get_makeups_members(): def get_makeups_members(ids=[]):
api = OdooAPI() api = OdooAPI()
cond = [['makeups_to_do','>', 0]] cond = [['makeups_to_do','>', 0]]
fields = ['id', 'name', 'display_std_points', 'display_ftop_points', 'shift_type', 'makeups_to_do']
if len(ids) > 0:
cond.append(['id','in', ids])
fields = ['id', 'name', 'display_std_points', 'display_ftop_points', 'shift_type', 'makeups_to_do', 'date_delay_stop']
res = api.search_read('res.partner', cond, fields) res = api.search_read('res.partner', cond, fields)
return res return res
......
...@@ -67,4 +67,13 @@ ...@@ -67,4 +67,13 @@
.btn_possible_member { .btn_possible_member {
margin: 0 1rem; margin: 0 1rem;
}
.member_name {
font-weight: bold;
}
.title_center {
display: flex;
justify-content: center;
} }
\ No newline at end of file
...@@ -56,7 +56,7 @@ function display_makeups_members() { ...@@ -56,7 +56,7 @@ function display_makeups_members() {
columns: [ columns: [
{ {
data: "id", data: "id",
title: '', title: "",
className: "dt-body-center", className: "dt-body-center",
orderable: false, orderable: false,
render: function (data) { render: function (data) {
...@@ -69,10 +69,29 @@ function display_makeups_members() { ...@@ -69,10 +69,29 @@ function display_makeups_members() {
title: "Nom" title: "Nom"
}, },
{ {
data: "shift_type", data: "id",
title: "Nb de points", title: "",
className: "dt-body-center",
orderable: false,
width: "10%",
render: function (data, type, row) {
return `<button class="btn--primary extend_delay_button" data-member-id="${row.id}">Augmenter le délai</button>`;
}
},
{
data: "date_delay_stop",
title: "<div class='title_center'>Limite du délai</div>",
className: "dt-body-center", className: "dt-body-center",
width: "10%", width: "10%",
render: function (data) {
return (data === false) ? "Pas de délai en cours" : new Date(data).toLocaleDateString();
}
},
{
data: "shift_type",
title: "<div class='title_center'>Nb de points</div>",
className: "dt-body-center",
width: "5%",
render: function (data, type, row) { render: function (data, type, row) {
if (data == 'ftop') { if (data == 'ftop') {
return row.display_ftop_points; return row.display_ftop_points;
...@@ -85,7 +104,7 @@ function display_makeups_members() { ...@@ -85,7 +104,7 @@ function display_makeups_members() {
}, },
{ {
data: "makeups_to_do", data: "makeups_to_do",
title: "Nb rattrapages", title: "<div class='title_center'>Nb rattrapages</div>",
className: "dt-body-center", className: "dt-body-center",
width: "10%", width: "10%",
render: function (data, type, full) { render: function (data, type, full) {
...@@ -212,6 +231,24 @@ function display_makeups_members() { ...@@ -212,6 +231,24 @@ function display_makeups_members() {
.hide(); .hide();
} }
}); });
$('#makeups_members_table').on('click', 'tbody td .extend_delay_button', function () {
const member_id = this.dataset.memberId;
const member = makeups_members.find(m => m.id == member_id);
let modal = $("#modal_extend_delay_template");
modal.find(".member_name").text(member.name);
openModal(
modal.html(),
() => {
extend_member_delay(member);
},
"Confirmer",
false
);
});
} }
/** /**
...@@ -276,10 +313,57 @@ function update_members_makeups(member_ids, action) { ...@@ -276,10 +313,57 @@ function update_members_makeups(member_ids, action) {
if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') { if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
err.msg += ' : ' + data.responseJSON.error; err.msg += ' : ' + data.responseJSON.error;
} }
report_JS_error(err, 'members_admin'); report_JS_error(err, 'members_admin-manage_makeups');
closeModal();
alert('Erreur serveur pour décrémenter les rattrapages. Veuillez contacer le service informatique.');
}
});
}
/**
* Send request to extend the member's delay, or create one if none open.
* @param {Object} member
*/
function extend_member_delay(member) {
openModal();
let today = new Date();
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));
let data = {
member_id: member.id,
duration: diff_days
};
$.ajax({
type: 'POST',
url: "/members/admin/regenerate_member_delay",
data: JSON.stringify(data),
dataType:"json",
traditional: true,
contentType: "application/json; charset=utf-8",
success: function(result) {
let i = makeups_members.findIndex(m => m.id == result.member_data.id);
makeups_members[i].date_delay_stop = result.member_data.date_delay_stop;
display_makeups_members();
closeModal();
},
error: function(data) {
err = {msg: "erreur serveur pour créer un délai", ctx: 'extend_member_delay'};
if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
err.msg += ' : ' + data.responseJSON.error;
}
report_JS_error(err, 'members_admin-manage_makeups');
closeModal(); closeModal();
alert('Erreur serveur pour décrémenter les rattrapages. Ré-essayez plus tard.'); alert('Erreur serveur pour créer un délai. Veuillez contacer le service informatique.');
} }
}); });
} }
......
...@@ -188,39 +188,39 @@ function set_subscription_area() { ...@@ -188,39 +188,39 @@ function set_subscription_area() {
retrieve_and_draw_shift_tempates({shift_listener: false}); retrieve_and_draw_shift_tempates({shift_listener: false});
$("#shifts_calendar_area").show(); $("#shifts_calendar_area").show();
// Cancel listeners from subscription page & set custom listeners // Cancel listeners from subscription page & set custom listeners
$(document).off("click", "#shifts_calendar_area button[data-select='Volant']"); $(document).off("click", "#shifts_calendar_area button[data-select='Volant']");
$(document).on("click", "#shifts_calendar_area button[data-select='Volant']", function() { $(document).on("click", "#shifts_calendar_area button[data-select='Volant']", function() {
// Subscribe to comitee/ftop shift // Subscribe to comitee/ftop shift
msg = (has_committe_shift === "True") msg = (has_committe_shift === "True")
? `Inscrire ${selected_member.name} au service des Comités ?` ? `Inscrire ${selected_member.name} au service des Comités ?`
: `Inscrire ${selected_member.name} en Volant ?`; : `Inscrire ${selected_member.name} en Volant ?`;
openModal( openModal(
msg, msg,
() => { () => {
shift_subscrition(2); shift_subscrition(2);
}, },
"Confirmer", "Confirmer",
false false
); );
}); });
$(document).off("click", ".shift"); $(document).off("click", ".shift");
$(document).on("click", ".shift", function() { $(document).on("click", ".shift", function() {
// Subscribe to shift template // Subscribe to shift template
let shift_template_id = select_shift_among_compact(null, this, false); // method from common.js let shift_template_id = select_shift_among_compact(null, this, false); // method from common.js
let shift_template_data = shift_templates[shift_template_id].data;// shift_templates: var from common.js let shift_template_data = shift_templates[shift_template_id].data;// shift_templates: var from common.js
let shift_template_name = get_shift_name(shift_template_data); let shift_template_name = get_shift_name(shift_template_data);
openModal( openModal(
`Inscrire ${selected_member.name} au créneau ${shift_template_name} ?`, `Inscrire ${selected_member.name} au créneau ${shift_template_name} ?`,
() => { () => {
shift_subscrition(1, parseInt(shift_template_id), shift_template_name); shift_subscrition(1, parseInt(shift_template_id), shift_template_name);
}, },
"Confirmer", "Confirmer",
false false
); );
}); });
} }
......
...@@ -127,7 +127,7 @@ function create_new_coop() { ...@@ -127,7 +127,7 @@ function create_new_coop() {
$('.chosen_associate_area').hide(); $('.chosen_associate_area').hide();
$('.member_choice').removeClass('choice_active'); $('.member_choice').removeClass('choice_active');
$(".remove_binome_icon").on("click", hide_chosen_associate); $(".remove_binome_icon").on("click", hide_chosen_associate);
$('input[name="binome"]').prop('checked',false); $('input[name="binome"]').prop('checked', false);
local_in_process = getLocalInProcess(); local_in_process = getLocalInProcess();
if (getLocalInProcess().length > 0) { if (getLocalInProcess().length > 0) {
empty_waiting_local_processes(); empty_waiting_local_processes();
...@@ -270,7 +270,7 @@ function store_new_coop(event) { ...@@ -270,7 +270,7 @@ function store_new_coop(event) {
} }
if ($('#associate_area').is(':visible')) { if ($('#associate_area').is(':visible')) {
// If user choose yes for binome, a type of association must be selected // If user choose yes for binome, a type of association must be selected
let associated_data_selected = false; let associated_data_selected = false;
if ( if (
......
...@@ -66,6 +66,7 @@ urlpatterns = [ ...@@ -66,6 +66,7 @@ urlpatterns = [
url(r'^delete_shift_template_registration$', admin.delete_shift_template_registration), url(r'^delete_shift_template_registration$', admin.delete_shift_template_registration),
url(r'^shift_subscription$', admin.shift_subscription), url(r'^shift_subscription$', admin.shift_subscription),
url(r'^admin/manage_attached$', admin.manage_attached), url(r'^admin/manage_attached$', admin.manage_attached),
url(r'^admin/regenerate_member_delay$', admin.regenerate_member_delay),
url(r'^admin/manage_attached/create_pair$', admin.create_pair), url(r'^admin/manage_attached/create_pair$', admin.create_pair),
url(r'^admin/manage_attached/delete_pair$', admin.delete_pair), url(r'^admin/manage_attached/delete_pair$', admin.delete_pair),
url(r'^get_makeups_members$', admin.get_makeups_members), url(r'^get_makeups_members$', admin.get_makeups_members),
......
...@@ -318,7 +318,7 @@ class CagetteShift(models.Model): ...@@ -318,7 +318,7 @@ class CagetteShift(models.Model):
coop_logger.error("Reopen shift : %s", str(e)) coop_logger.error("Reopen shift : %s", str(e))
return response return response
def create_delay(self, data, duration=28): def create_delay(self, data, duration=28, ext_name="Extension créée depuis l'espace membre"):
""" """
Create a delay for a member. Create a delay for a member.
If no duration is specified, a delay is by default 28 days from the given start_date. If no duration is specified, a delay is by default 28 days from the given start_date.
...@@ -327,14 +327,16 @@ class CagetteShift(models.Model): ...@@ -327,14 +327,16 @@ class CagetteShift(models.Model):
Else, create a 28 days delay. Else, create a 28 days delay.
Args: Args:
idPartner: int data
start_date: string date at iso format (eg. "2019-11-19") idPartner: int
Date from which the delay end date is calculated start_date: string date at iso format (eg. "2019-11-19")
(optionnal) extension_beginning: string date at iso format Date from which the delay end date is calculated
If specified, will be the actual starting date of the extension. (optionnal) extension_beginning: string date at iso format
Should be inferior than start_date. If specified, will be the actual starting date of the extension.
(at creation only: odoo ignores delays if today's not inside) Should be inferior than start_date.
(at creation only: odoo ignores delays if today's not inside)
duration: nb of days duration: nb of days
ext_name: will be displayed in odoo extensions list
""" """
action = 'create' action = 'create'
...@@ -392,7 +394,7 @@ class CagetteShift(models.Model): ...@@ -392,7 +394,7 @@ class CagetteShift(models.Model):
"type_id": ext_type_id, "type_id": ext_type_id,
"date_start": starting_date.isoformat(), "date_start": starting_date.isoformat(),
"date_stop": ending_date.isoformat(), "date_stop": ending_date.isoformat(),
"name": "Extension créée depuis l'espace membre" "name": ext_name
} }
response = self.o_api.create('shift.extension', fields) response = self.o_api.create('shift.extension', fields)
......
...@@ -56,7 +56,15 @@ ...@@ -56,7 +56,15 @@
</div> </div>
<div id="templates" style="display:none;"></div> <div id="templates" style="display:none;">
<div id="modal_extend_delay_template">
<p>
Vous vous apprêtez à rallonger le délai de
<span class="member_name"></span>
pour une durée de 6 mois à partir d'aujourd'hui.
</p>
</div>
</div>
</div> </div>
<script src='{% static "js/all_common.js" %}?v=1651853225'></script> <script src='{% static "js/all_common.js" %}?v=1651853225'></script>
......
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