def __init__(self, id, revision_id=None): """Create a `Patron` instance. Patron instances are not stored in the database but are indexed in ElasticSearch. """ _id = int(id) # internally it is an int _datastore = current_app.extensions["security"].datastore # if not _id throw PatronNotFoundError(_id) user = _datastore.get_user(_id) if not user: raise PatronNotFoundError(_id) self._user = user self.id = self._user.id # set revision as it is needed by the indexer but always to the same # value as we don't need it self.revision_id = 1 self._profile = UserProfile.get_by_userid(id) self.name = self._profile.full_name if self._profile else "" self.email = self._user.email # currently no support for patrons affiliated to different # locations, return only the default location pid_value, _ = current_app_ils.get_default_location_pid self.location_pid = pid_value # add all fields to the dict so they can be accessed as a dict too super().__init__(self.dumps())
def test_patron_not_found(app): """Test PatronNotFoundError.""" patron_pid = "1" msg = "Patron with PID `{patron_pid}` was not found." with pytest.raises(PatronNotFoundError) as ex: raise PatronNotFoundError(patron_pid) assert ex.value.code == PatronNotFoundError.code assert ex.value.description == msg.format(patron_pid=patron_pid)
def get_patron(patron_pid): """Return the patron object given the patron_pid.""" if not patron_pid: raise PatronNotFoundError(patron_pid) if str(patron_pid) == str(SystemAgent.id): return SystemAgent() return Patron(patron_pid)
def get_patron(cls, patron_pid): """Return the patron object given the patron_pid.""" if not patron_pid: raise PatronNotFoundError(patron_pid) SystemAgent = current_app.config["ILS_PATRON_SYSTEM_AGENT_CLASS"] if str(patron_pid) == str(SystemAgent.id): return SystemAgent() return cls(patron_pid)
def send_email_after_loan_change(_, prev_loan, loan, trigger): """Send email notification when the loan changes.""" _datastore = current_app.extensions["security"].datastore patron_pid = loan["patron_pid"] patron = _datastore.get_user(patron_pid) if not patron: raise PatronNotFoundError(patron_pid) if not patron.email: msg = "Patron with PID {} has no email address".format(patron_pid) raise MissingRequiredParameterError(description=msg) send_ils_mail(loan_message_factory(), prev_loan, loan, trigger, recipients=[patron.email])
def __init__(self, id, revision_id=None): """Create a `Patron` instance. Patron instances are not stored in the database but are indexed in ElasticSearch. """ _id = int(id) # internally it is an int _datastore = current_app.extensions["security"].datastore # if not _id throw PatronNotFoundError(_id) user = _datastore.get_user(_id) if not user: raise PatronNotFoundError(_id) self._user = user self.id = self._user.id # set revision as it is needed by the indexer but always to the same # value as we don't need it self.revision_id = 1 self._profile = UserProfile.get_by_userid(id) self.name = self._profile.full_name if self._profile else "" self.email = self._user.email
def get_patron(patron_pid): """Return the patron object given the patron_pid.""" if not patron_pid: raise PatronNotFoundError(patron_pid) return Patron(patron_pid)
def ensure_patron_exists(self, patron_pid): """Ensure patron exists or raise.""" try: current_app_ils.patron_cls.get_patron(patron_pid) except PatronNotFoundError: raise PatronNotFoundError(patron_pid)
def anonymize_patron_data(patron_pid, force=False): """Anonymize all the data/activity related to the given patron pid.""" if patron_pid is None: raise ValueError("No patron pid was provided.") SystemAgent = current_app.config["ILS_PATRON_SYSTEM_AGENT_CLASS"] if str(patron_pid) == str(SystemAgent.id): raise ValueError("The patron pid cannot be the SystemAgent") try: patron = current_app_ils.patron_cls.get_patron(patron_pid) except PatronNotFoundError: patron = None if not force: raise PatronNotFoundError(patron_pid) n_loans = get_active_loans_by_patron_pid(patron_pid).count() if n_loans > 0: raise AnonymizationActiveLoansError( "Cannot delete user {0}: found {1} active loans.".format( patron_pid, n_loans)) OrderSearch = current_ils_acq.order_search_cls n_orders = ( OrderSearch().get_ongoing_orders_by_patron_pid(patron_pid).count()) if n_orders > 0: raise AnonymizationActiveLoansError( "Cannot delete user {0}: found {1} active orders.".format( patron_pid, n_orders)) # get anonymous patron values cls = current_app.config["ILS_PATRON_ANONYMOUS_CLASS"] anonymous_patron_fields = cls().dumps_loader() patron_loans = get_loans_by_patron_pid(patron_pid).scan() Loan = current_circulation.loan_record_cls indices = 0 for hit in patron_loans: loan = Loan.get_record_by_pid(hit.pid) completed = (current_app.config["CIRCULATION_STATES_LOAN_CANCELLED"] + current_app.config["CIRCULATION_STATES_LOAN_COMPLETED"]) if loan["state"] not in completed: params = deepcopy(loan) params.update( dict( cancel_reason="Loan request cancelled by the system.", transaction_user_pid=str(SystemAgent.id), )) loan = current_circulation.circulation.trigger( loan, **dict(params, trigger="cancel")) loan["patron_pid"] = anonymous_patron_fields["pid"] loan["patron"] = anonymous_patron_fields loan.commit() current_circulation.loan_indexer().index(loan) indices += 1 BorrowingRequestsSearch = current_ils_ill.borrowing_request_search_cls patron_borrowing_requests = ( BorrowingRequestsSearch().search_by_patron_pid(patron_pid).scan()) BorrowingRequest = current_ils_ill.borrowing_request_record_cls indexer = current_ils_ill.borrowing_request_indexer_cls() for hit in patron_borrowing_requests: borrowing_request = BorrowingRequest.get_record_by_pid(hit.pid) borrowing_request["patron"] = anonymous_patron_fields borrowing_request["patron_pid"] = anonymous_patron_fields["pid"] borrowing_request.commit() indexer.index(borrowing_request) indices += 1 DocumentRequestSearch = current_app_ils.document_request_search_cls patron_document_requests = ( DocumentRequestSearch().search_by_patron_pid(patron_pid).scan()) DocumentRequest = current_app_ils.document_request_record_cls for hit in patron_document_requests: document_request = DocumentRequest.get_record_by_pid(hit.pid) if document_request["state"] == "PENDING": document_request["state"] = "DECLINED" document_request["decline_reason"] = "USER_CANCEL" document_request["patron"] = anonymous_patron_fields document_request["patron_pid"] = anonymous_patron_fields["pid"] document_request.commit() current_app_ils.document_request_indexer.index(document_request) indices += 1 patron_acquisitions = OrderSearch().search_by_patron_pid(patron_pid).scan() Order = current_ils_acq.order_record_cls for hit in patron_acquisitions: acquisition = Order.get_record_by_pid(hit.pid) for line in acquisition["order_lines"]: if line["patron_pid"] == patron_pid: line["patron_pid"] = anonymous_patron_fields["pid"] acquisition.commit() current_ils_acq.order_indexer.index(acquisition) indices += 1 # delete rows from db dropped = delete_user_account(patron_pid) # anonymize recipient id in emails emails = anonymize_patron_in_email_logs(patron_pid) db.session.commit() if patron: try: patron_indexer = current_app_ils.patron_indexer patron_indexer.delete(patron) except NotFoundError: pass return dropped, indices, emails