Koha/koha-tmpl/intranet-tmpl/prog/js/members-menu.js
Magnus Enger 6fec4ea0df
Bug 26170: Add protected status for patrons
This set of patches makes it possible to protect patrons from being accidetally
deleted or merged with other patrons, from the UI and from (well behaved) cron
jobs. The following subroutines are affected:
- Koha::Patron::delete
- Koha::Patron::merge_with
- Koha::Patron::safe_to_delete
- C4::Members::GetBorrowersToExpunge

Please note:
- This does not intend to protect patrons from being edited, only from being
  deleted

To test:

* Tests
- Run the affected tests:
  prove t/db_dependent/Members.t
  prove t/db_dependent/Koha/Patrons.t

* Editing protected status and manual deletion
- Add a new user, note the presence of the "Protected" field under "Library
  management", but leave it at the default "No", for now.
- Note that "Protected" is displayed in the "Library use" section of the patron
  details.
- Note that More > Delete is avaiable as an action when the patron is saved
- Edit the user and set "Protected" to "Yes"
- Note that More > Delete is now disabled, with a note that the patron is protected

* Batch patron deletion
- Go to Tools > Batch patron deletion and anonymization
- Check the box for "Verify you want to delete patrons"
- Choose the category of your protected patron for "whose patron category is"
  and click "Next" to run the actual deletion
- Check that your protected patron was not deleted

* Merging patrons
- Make sure you have two patrons with similar names or the same category, so
  you can find them with one search. One should be protected, one not.
- Search for the patrons, tick their boxes and click on "Merge selected patrons"
- Select one of the patrons as the "patron to keep".
. Click on "Merge patrons"
- "No valid patrons to merge were found" should be shown
- Repeat this with the other patron as the "patron to keep"
(A future enhancement could be to not allow a protected patron to be selected for
merging in the first place.)

* misc/cronjobs/delete_patrons.pl
- Make sure you have a protected patron, in a category with at least one more
  patron.
- Run something like this (at least in ktd):
  $ perl misc/cronjobs/delete_patrons.pl --category_code <code> -v --confirm
  (Replace <code> with the actual categorycode.)
- Make sure the borrowernumber of the protected patron is not mentioned in the
  output of the script.
- Check the protected patron was not deleted
- Check the non-protected patrons were deleted

* REST API (with ktd)
- Make sure you still have a protected patron, and note their borrowernumber
- Enable RESTBasicAuth and restart all the things
- Run these two commands from the command line on the host:
  $ curl -u koha:koha --request GET "http://localhost:8081/api/v1/patrons/54"
  $ curl -u koha:koha --request DELETE "http://localhost:8081/api/v1/patrons/54"
  (Replace 54 with the actual borrowernumber of your protected patron.)
- The first curl command should give you the patron details. The second should
  give this output:
  {"error":"Protected patrons cannot be deleted","error_code":"is_protected"}

There could be more functions/scripts where patrons are deleted that I have not
thought about. Please report them on the bug if you find any!

Update 2023-10-19: Fix "More > Delete" on patron, so link can not be clicked.
Update 2023-10-19: Rebase

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
2023-11-01 17:23:06 -03:00

169 lines
6.5 KiB
JavaScript

/* global borrowernumber advsearch dateformat __ CAN_user_borrowers_delete_borrowers CAN_user_borrowers_edit_borrowers number_of_adult_categories destination Sticky Cookies*/
$(document).ready(function(){
searchfield_date_tooltip("");
searchfield_date_tooltip('_filter');
$("#searchfieldstype").change(function() {
searchfield_date_tooltip("");
});
$("#searchfieldstype_filter").change(function() {
searchfield_date_tooltip('_filter');
});
if( CAN_user_borrowers_delete_borrowers ){
$("#deletepatron").click(function(){
if( $(this).data("toggle") == "tooltip"){ // Disabled menu option has tooltip attribute
e.preventDefault();
} else {
window.location='/cgi-bin/koha/members/deletemem.pl?member=' + borrowernumber;
}
});
}
if( CAN_user_borrowers_edit_borrowers ){
$("#renewpatron").click(function(){
confirm_reregistration();
$(".btn-group").removeClass("open");
return false;
});
$("#updatechild").click(function(e){
if( $(this).data("toggle") == "tooltip"){ // Disabled menu option has tooltip attribute
e.preventDefault();
} else {
update_child();
$(".btn-group").removeClass("open");
}
});
}
$(".delete_message").click(function(){
return window.confirm( __("Are you sure you want to delete this message? This cannot be undone.") );
});
$("#updatechild, #patronflags, #renewpatron, #deletepatron, #exportbarcodes").tooltip();
$("#exportcheckins").click(function(){
export_barcodes();
$(".btn-group").removeClass("open");
return false;
});
$("#printsummary").click(function(){
printx_window("page");
$(".btn-group").removeClass("open");
return false;
});
$("#printslip").click(function(){
printx_window("slip");
$(".btn-group").removeClass("open");
return false;
});
$("#printquickslip").click(function(){
printx_window("qslip");
$(".btn-group").removeClass("open");
return false;
});
$("#print_overdues").click(function(){
window.open("/cgi-bin/koha/members/print_overdues.pl?borrowernumber=" + borrowernumber, "printwindow");
$(".btn-group").removeClass("open");
return false;
});
$("#printcheckinslip").click(function(){
printx_window("checkinslip");
$(".btn-group").removeClass("open");
return false;
});
$("#printclearscreen").click(function(){
printx_window("slip");
window.location.replace("/cgi-bin/koha/circ/circulation.pl");
});
$("#printclearscreenq").click(function(){
printx_window("qslip");
window.location.replace("/cgi-bin/koha/circ/circulation.pl");
});
$("#searchtohold").click(function(){
searchToHold();
return false;
});
$("#select_patron_messages").on("change",function(){
$("#borrower_message").val( $(this).val() );
});
$("#patronImageEdit").on("shown.bs.modal", function(){
startup();
});
$(".edit-patronimage").on("click", function(e){
e.preventDefault();
var borrowernumber = $(this).data("borrowernumber");
var cardnumber = $(this).data("cardnumber");
var modalTitle = $(this).attr("title");
$("#patronImageEdit .modal-title").text(modalTitle);
$("#patronImageEdit").modal("show");
$("#patronImageEdit").on("hidden.bs.modal", function(){
/* Stop using the user's camera when modal is closed */
let viewfinder = document.getElementById("viewfinder");
if( viewfinder.srcObject ){
viewfinder.srcObject.getTracks().forEach( track => {
if( track.readyState == 'live' && track.kind === 'video'){
track.stop();
}
});
}
});
});
});
function searchfield_date_tooltip(filter) {
var field = "#searchmember" + filter;
var type = "#searchfieldstype" + filter;
if ( $(type).val() == 'dateofbirth' ) {
var MSG_DATE_FORMAT = "";
if( dateformat == 'us' ){
MSG_DATE_FORMAT = __("Dates of birth should be entered in the format 'MM/DD/YYYY'");
} else if( dateformat == 'iso' ){
MSG_DATE_FORMAT = __("Dates of birth should be entered in the format 'YYYY-MM-DD'");
} else if( dateformat == 'metric' ){
MSG_DATE_FORMAT = __("Dates of birth should be entered in the format 'DD/MM/YYYY'");
} else if( dateformat == 'dmydot' ){
MSG_DATE_FORMAT = __("Dates of birth should be entered in the format 'DD.MM.YYYY'");
}
$(field).attr("title", MSG_DATE_FORMAT).tooltip('show');
} else {
$(field).tooltip('destroy');
}
}
function confirm_updatechild() {
var is_confirmed = window.confirm( __("Are you sure you want to update this child to an Adult category? This cannot be undone.") );
if (is_confirmed) {
window.location='/cgi-bin/koha/members/update-child.pl?op=update&borrowernumber=' + borrowernumber;
}
}
function update_child() {
if( number_of_adult_categories > 1 ){
window.open('/cgi-bin/koha/members/update-child.pl?op=multi&borrowernumber=' + borrowernumber,'UpdateChild','width=400,height=300,toolbar=no,scrollbars=yes,resizable=yes');
} else {
confirm_updatechild();
}
}
function confirm_reregistration() {
var is_confirmed = window.confirm( __("Are you sure you want to renew this patron's registration?") );
if (is_confirmed) {
window.location = '/cgi-bin/koha/members/setstatus.pl?borrowernumber=' + borrowernumber + '&destination=' + destination + '&reregistration=y';
}
}
function export_barcodes() {
window.open('/cgi-bin/koha/members/readingrec.pl?borrowernumber=' + borrowernumber + '&op=export_barcodes');
}
var slip_re = /slip/;
function printx_window(print_type) {
var handler = print_type.match(slip_re) ? "printslip" : "summary-print";
window.open("/cgi-bin/koha/members/" + handler + ".pl?borrowernumber=" + borrowernumber + "&print=" + print_type, "printwindow");
return false;
}
function searchToHold(){
var date = new Date();
date.setTime(date.getTime() + (10 * 60 * 1000));
Cookies.set("holdfor", borrowernumber, { path: "/", expires: date, sameSite: 'Lax' });
location.href="/cgi-bin/koha/catalogue/search.pl";
}