6fec4ea0df
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>
385 lines
9.2 KiB
YAML
385 lines
9.2 KiB
YAML
---
|
|
type: object
|
|
properties:
|
|
patron_id:
|
|
type: integer
|
|
description: Internal patron identifier
|
|
cardnumber:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: library assigned user identifier
|
|
surname:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: patron's last name
|
|
firstname:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: patron's first name
|
|
middle_name:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: patron's middle name
|
|
title:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: patron's title
|
|
other_name:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: any other names associated with the patron
|
|
initials:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: initials of the patron
|
|
pronouns:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: pronouns of the patron
|
|
street_number:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: street number of patron's primary address
|
|
street_type:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: street type of patron's primary address
|
|
address:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: first address line of patron's primary address
|
|
address2:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: second address line of patron's primary address
|
|
city:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: city or town of patron's primary address
|
|
state:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: state or province of patron's primary address
|
|
postal_code:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: zip or postal code of patron's primary address
|
|
country:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: country of patron's primary address
|
|
email:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: primary email address for patron's primary address
|
|
phone:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: primary phone number for patron's primary address
|
|
mobile:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: the other phone number for patron's primary address
|
|
fax:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: fax number for patron's primary address
|
|
secondary_email:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: secondary email address for patron's primary address
|
|
secondary_phone:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: secondary phone number for patron's primary address
|
|
altaddress_street_number:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: street number of patron's alternate address
|
|
altaddress_street_type:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: street type of patron's alternate address
|
|
altaddress_address:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: first address line of patron's alternate address
|
|
altaddress_address2:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: second address line of patron's alternate address
|
|
altaddress_city:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: city or town of patron's alternate address
|
|
altaddress_state:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: state or province of patron's alternate address
|
|
altaddress_postal_code:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: zip or postal code of patron's alternate address
|
|
altaddress_country:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: country of patron's alternate address
|
|
altaddress_email:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: email address for patron's alternate address
|
|
altaddress_phone:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: phone number for patron's alternate address
|
|
date_of_birth:
|
|
type:
|
|
- string
|
|
- "null"
|
|
format: date
|
|
description: patron's date of birth
|
|
library_id:
|
|
type: string
|
|
description: Internal identifier for the patron's home library
|
|
category_id:
|
|
type: string
|
|
description: Internal identifier for the patron's category
|
|
date_enrolled:
|
|
type:
|
|
- string
|
|
- "null"
|
|
format: date
|
|
description: date the patron was added to Koha
|
|
expiry_date:
|
|
type:
|
|
- string
|
|
- "null"
|
|
format: date
|
|
description: date the patron's card is set to expire
|
|
date_renewed:
|
|
type:
|
|
- string
|
|
- "null"
|
|
format: date
|
|
description: date the patron's card was last renewed
|
|
incorrect_address:
|
|
type:
|
|
- boolean
|
|
- "null"
|
|
description: set to 1 if library marked this patron as having an unconfirmed address
|
|
patron_card_lost:
|
|
type:
|
|
- boolean
|
|
- "null"
|
|
description: set to 1 if library marked this patron as having lost his card
|
|
restricted:
|
|
type: boolean
|
|
readOnly: true
|
|
description: If any restriction applies to the patron
|
|
staff_notes:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: a note on the patron's account
|
|
relationship_type:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: used for children to include the relationship to their guarantor
|
|
gender:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: patron's gender
|
|
userid:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: patron's login
|
|
opac_notes:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: a note on the patron's account visible in OPAC and staff interface
|
|
altaddress_notes:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: a note related to patron's alternate address
|
|
statistics_1:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: a field that can be used for any information unique to the library
|
|
statistics_2:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: a field that can be used for any information unique to the library
|
|
autorenew_checkouts:
|
|
type: boolean
|
|
description: indicate whether auto-renewal is allowed for patron
|
|
altcontact_firstname:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: first name of alternate contact for the patron
|
|
altcontact_surname:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: surname or last name of the alternate contact for the patron
|
|
altcontact_address:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: the first address line for the alternate contact for the patron
|
|
altcontact_address2:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: the second address line for the alternate contact for the patron
|
|
altcontact_city:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: the city for the alternate contact for the patron
|
|
altcontact_state:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: the state for the alternate contact for the patron
|
|
altcontact_postal_code:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: the zipcode for the alternate contact for the patron
|
|
altcontact_country:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: the country for the alternate contact for the patron
|
|
altcontact_phone:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: the phone number for the alternate contact for the patron
|
|
sms_number:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: the mobile phone number where the patron would like to receive notices (if
|
|
SMS turned on)
|
|
sms_provider_id:
|
|
type:
|
|
- integer
|
|
- "null"
|
|
description: the provider of the mobile phone number defined in smsalertnumber
|
|
privacy:
|
|
type: integer
|
|
description: patron's privacy settings related to their checkout history
|
|
privacy_guarantor_checkouts:
|
|
type: integer
|
|
description: controls if relatives can see this patron's checkouts
|
|
privacy_guarantor_fines:
|
|
type: boolean
|
|
description: controls if relatives can see this patron's fines
|
|
check_previous_checkout:
|
|
type: string
|
|
description: produce a warning for this patron if this item has previously been checked
|
|
out to this patron if 'yes', not if 'no', defer to category setting if
|
|
'inherit'
|
|
updated_on:
|
|
type: string
|
|
format: date-time
|
|
description: time of last change could be useful for synchronization with external
|
|
systems (among others)
|
|
last_seen:
|
|
type:
|
|
- string
|
|
- "null"
|
|
format: date-time
|
|
description: last time a patron has been seen (connected at the OPAC or staff interface)
|
|
lang:
|
|
type: string
|
|
description: lang to use to send notices to this patron
|
|
login_attempts:
|
|
type:
|
|
- integer
|
|
- "null"
|
|
description: number of failed login attemps
|
|
overdrive_auth_token:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: persist OverDrive auth token
|
|
anonymized:
|
|
type: boolean
|
|
readOnly: true
|
|
description: If the patron has been anonymized
|
|
extended_attributes:
|
|
type: array
|
|
description: patron's extended attributes
|
|
items:
|
|
$ref: "patron_extended_attribute.yaml"
|
|
checkouts_count:
|
|
type:
|
|
- integer
|
|
- "null"
|
|
description: Number of checkouts
|
|
overdues_count:
|
|
type:
|
|
- integer
|
|
- "null"
|
|
description: Number of overdued checkouts
|
|
account_balance:
|
|
type:
|
|
- number
|
|
- "null"
|
|
description: Balance of the patron's account
|
|
library:
|
|
type:
|
|
- object
|
|
- "null"
|
|
description: Library of the patron
|
|
protected:
|
|
type:
|
|
- boolean
|
|
description: Protected status of the patron
|
|
additionalProperties: false
|
|
required:
|
|
- surname
|
|
- library_id
|
|
- category_id
|