#
# INVENIO-SIP2
# Copyright (C) 2020 UCLouvain
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Models for Invenio-SIP2."""
from enum import Enum
from .proxies import current_sip2 as acs_system
[docs]class PatronStatusTypes(Enum):
"""Enum class to list all possible patron status types."""
CHARGE_PRIVILEGES_DENIED = 'charge_privileges_denied'
RENEWAL_PRIVILEGES_DENIED = 'renewal_privileges_denied'
RECALL_PRIVILEGES_DENIED = 'recall_privileges_denied'
HOLD_PRIVILEGES_DENIED = 'hold_privileges_denied'
CARD_REPORTED_LOST = 'card_reported_lost'
TOO_MANY_ITEMS_CHARGED = 'too_many_items_charged'
TOO_MANY_ITEMS_OVERDUE = 'too_many_items_overdue'
TOO_MANY_RENEWALS = 'too_many_renewals'
TOO_MANY_CLAIMS_OF_ITEMS_RETURNED = 'too_many_claims_of_items_returned'
TOO_MANY_ITEMS_LOST = 'too_many_items_lost'
EXCESSIVE_OUTSTANDING_FINES = 'excessive_outstanding_fines'
EXCESSIVE_OUTSTANDING_FEES = 'excessive_outstanding_fees'
RECALL_OVERDUE = 'recall_overdue'
TOO_MANY_ITEMS_BILLED = 'too_many_items_billed'
[docs]class PatronStatus(object):
"""Class to define patron status."""
def __init__(self):
"""Constructor."""
self.patron_status_types = {}
def __str__(self):
"""Sip2 string representation."""
patron_status_text = ''
for status_type in PatronStatusTypes:
patron_status_text += 'Y' \
if self.patron_status_types.get(status_type) else ' '
return patron_status_text
[docs] def add_patron_status_type(self, patron_status_type):
"""Add patron status.
:param patron_status_type: Enum of patron status type
Add ``patron_status_type`` indicates that the condition is true.
raise exception if patron status type does not exist.
"""
if patron_status_type not in PatronStatusTypes:
raise Exception(msg='patron status type does not exist')
self.patron_status_types[patron_status_type] = True
[docs]class SelfcheckPatronStatus(dict):
"""Class representing patron information handler response."""
def __init__(self, patron_status, language, **kwargs):
"""Constructor.
:param patron_id - patron identifier (e.g. id, barcode, ...)
:param patron_name - full name of the patron
:param institution_id - institution id (or code) of the patron
:param language - iso-639-2 language
:param kwargs - optional fields
"""
# required properties
self['patron_status'] = patron_status
self['language'] = language
self['screen_messages'] = []
# optional properties
for key, value in kwargs.items():
if value:
self[key] = value
[docs]class SelfcheckCheckin(dict):
"""Class representing checkin handler response."""
def __init__(self, permanent_location, checkin=False, alert=False,
magnetic_media=False, resensitize=False, **kwargs):
"""Constructor.
:param permanent_location - permanent_location of the item
:param checkin - checkin operation is success or not
:param alert - indicate if the selcheck will generate sound alert
:param magnetic_media - indicate the presence of magnetic media
:param resensitize - resensitize an item ?
:param kwargs - optional fields
"""
# required properties
self['checkin'] = checkin
self['alert'] = alert
self['magnetic_media'] = magnetic_media
self['resensitize'] = resensitize
self['permanent_location'] = permanent_location
self['screen_messages'] = []
# optional properties
for key, value in kwargs.items():
if value:
self[key] = value
@property
def is_success(self):
"""Shortcut for checkin."""
return self.get('checkin')
@property
def resensitize(self):
"""Shortcut for resensitize."""
return self.get('resensitize')
@property
def has_magnetic_media(self):
"""Shortcut for desensitize."""
return self.get('magnetic_media')
@property
def sound_alert(self):
"""Shortcut for alert."""
return self.get('alert')
[docs]class SelfcheckCheckout(dict):
"""Class representing checkout handler response."""
def __init__(self, title_id, checkout=False, renewal=False,
magnetic_media=False, desensitize=False, **kwargs):
"""Constructor.
:param title_id - title_id (e.g. title, identifier, ...)
:param checkout - checkout operation is success or not
:param renewal - renewal operation is success or not
:param magnetic_media - indicate the presence of magnetic media
:param desensitize - desensitize an item ?
:param kwargs - optional fields
"""
# required properties
self['checkout'] = checkout
self['renewal'] = renewal
self['magnetic_media'] = magnetic_media
self['desensitize'] = desensitize
self['title_id'] = title_id
self['screen_messages'] = []
# optional properties
for key, value in kwargs.items():
if value:
self[key] = value
@property
def is_success(self):
"""Shortcut for checkout ok."""
return self.get('checkout')
@property
def is_renewal(self):
"""Shortcut for renewal ok."""
return self.get('renewal')
@property
def due_date(self):
"""Shortcut for renewal ok."""
return self.get('due_date', '')
@property
def desensitize(self):
"""Shortcut for desensitize."""
return self.get('desensitize')
@property
def has_magnetic_media(self):
"""Shortcut for desensitize."""
return self.get('magnetic_media')
[docs]class SelfcheckHold(dict):
"""Class representing hold handler response."""
def __init__(self, hold=False, available=False, **kwargs):
"""Constructor.
:param hold - hold operation is success or not
:param available - item available or not
:param kwargs - optional fields
"""
# required properties
self['hold'] = hold
self['available'] = available
self['screen_messages'] = []
# optional properties
for key, value in kwargs.items():
if value:
self[key] = value
@property
def is_success(self):
"""Shortcut for hold ok."""
return self.get('hold')
@property
def is_available(self):
"""Shortcut for available."""
return self.get('available')
[docs]class SelfcheckRenew(dict):
"""Class representing renew handler response."""
def __init__(self, title_id, renew=False, renewal=False,
magnetic_media=False, desensitize=False, **kwargs):
"""Constructor.
:param title_id - title_id (e.g. title, identifier, ...)
:param renew - renew operation is success or not
:param renewal - renewal operation is success or not
:param magnetic_media - indicate the presence of magnetic media
:param desensitize - desensitize an item ?
:param kwargs - optional fields
"""
# required properties
self['renew'] = renew
self['renewal'] = renewal
self['magnetic_media'] = magnetic_media
self['desensitize'] = desensitize
self['title_id'] = title_id
self['due_date'] = acs_system.sip2_current_date
self['screen_messages'] = []
# optional properties
for key, value in kwargs.items():
if value:
self[key] = value
@property
def is_success(self):
"""Shortcut for renew ok."""
return self.get('renew')
@property
def is_renewal(self):
"""Shortcut for renewal ok."""
return self.get('renewal')
@property
def desensitize(self):
"""Shortcut for desensitize."""
return self.get('desensitize')
@property
def has_magnetic_media(self):
"""Shortcut for desensitize."""
return self.get('magnetic_media')
[docs]class SelfcheckLanguage(Enum):
"""Enum class to list all available language."""
# SIP2 supported Language
UNKNOWN = '000'
ENGLISH = '001'
FRENCH = '002'
GERMAN = '003'
ITALIAN = '004'
DUTCH = '005'
SWEDISH = '006'
FINNISH = '007'
SPANISH = '008'
DANISH = '009'
PORTUGUESE = '010'
CANADIAN_FRENCH = '011'
NORWEGIAN = '012'
HEBREW = '013'
JAPANESE = '014'
RUSSIAN = '015'
ARABIC = '016'
POLISH = '017'
GREEK = '018'
CHINESE = '019'
KOREAN = '020'
NORTH_AMERICAN_SPANISH = '021'
TAMIL = '022'
MALAY = '023'
UNITED_KINGDOM = '024'
ICELANDIC = '025'
BELGIAN = '026'
TAIWANESE = '027'
# ISO 639-2 common Language mapping
und = UNKNOWN
eng = ENGLISH
fre = FRENCH
ger = GERMAN
ita = ITALIAN
dut = DUTCH
swe = SWEDISH
fin = FINNISH
spa = SPANISH
dan = DANISH
por = PORTUGUESE
nor = NORWEGIAN
heb = HEBREW
jpn = JAPANESE
rus = RUSSIAN
pol = POLISH
gre = GREEK
chi = CHINESE
zho = CHINESE
kor = KOREAN
tam = TAMIL
may = MALAY
msa = MALAY
ice = ICELANDIC
isl = ICELANDIC
[docs]class SelfcheckSecurityMarkerType(object):
"""Class to handle all available security marker type."""
OTHER = '00'
NONE = '01'
TATTLE_TAPE_SECURITY_STRIP = '02'
WHISPHER_TAPE = '03'
[docs]class SelfcheckFeeType(object):
"""Class to handle all available fee type."""
OTHER = '01'
ADMINISTRATIVE = '02'
DAMAGE = '03'
OVERDUE = '04'
PROCESSING = '05'
RENTAL = '06'
REPLACEMENT = '07'
COMPUTER_ACCESS_CHARGE = '08'
HOLD_FEE = '09'
[docs]class SelfcheckCirculationStatus(object):
"""Class to handle all available circulation status of an item."""
OTHER = '01'
ON_ORDER = '02'
AVAILABLE = '03'
CHARGED = '04'
CHARGED_RECALL = '05' # not to be recalled until earliest recall date
IN_PROCESS = '06'
RECALLED = '07'
WAITING_ON_HOLD_SHELF = '08'
WAITING_TO_RESHELF = '09'
IN_TRANSIT = '10'
CLAIMED_RETURNED = '11'
LOST = '12'
MISSING = '13'
[docs]class SelfcheckSummary:
"""Class representing summary."""
fields = [
'hold_items',
'overdue_items',
'charged_items',
'fine_items',
'recall_items',
'unavailable_items',
]
def __init__(self, text):
"""Init."""
from .utils import decode_char_to_bool
self.hold_items = decode_char_to_bool(text[0:])
self.overdue_items = decode_char_to_bool(text[1])
self.charged_items = decode_char_to_bool(text[2])
self.fine_items = decode_char_to_bool(text[3])
self.recall_items = decode_char_to_bool(text[4])
self.unavailable_items = decode_char_to_bool(text[5])
[docs] def is_needed(self, key):
"""Check if the given information is needed."""
return getattr(self, key) or False