diff --git a/modules/bibcirculation/lib/bibcirculation_utils.py b/modules/bibcirculation/lib/bibcirculation_utils.py index f153194af..afd2ba7c6 100644 --- a/modules/bibcirculation/lib/bibcirculation_utils.py +++ b/modules/bibcirculation/lib/bibcirculation_utils.py @@ -1,702 +1,702 @@ # -*- coding: utf-8 -*- ## ## This file is part of Invenio. ## Copyright (C) 2008, 2009, 2010, 2011 CERN. ## ## Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## Invenio 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 ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """BibCirculation Utils: Auxiliary methods of BibCirculation """ __revision__ = "$Id$" from invenio.search_engine_utils import get_fieldvalues from invenio.bibtask import task_low_level_submission import invenio.bibcirculation_dblayer as db from invenio.urlutils import create_html_link from invenio.config import CFG_SITE_URL, CFG_TMPDIR from invenio.bibcirculation_config import CFG_BIBCIRCULATION_AMAZON_ACCESS_KEY, \ CFG_BIBCIRCULATION_WORKING_DAYS, \ CFG_BIBCIRCULATION_HOLIDAYS from invenio.messages import gettext_set_language import datetime, time, re -DICC_REGEXP = re.compile("^\{('[^']*': ?('[^']*'|[0-9]*|None)(, ?'[^']*': ?('[^']*'|[0-9]*|None))*)?\}$") +DICC_REGEXP = re.compile("^\{('[^']*': ?('[^']*'|\"[^\"]+\"|[0-9]*|None)(, ?'[^']*': ?('[^']*'|\"[^\"]+\"|[0-9]*|None))*)?\}$") def hold_request_mail(recid, borrower_id): """ Create the mail who will be sent for each hold requests. @param recid: identify the record. Primary key of bibrec. @type recid: int @param borrower_id: identify the borrower. Primary key of crcBORROWER. @type borrower_id: int @return email(body) """ (book_title, book_year, book_author, book_isbn, book_editor) = book_information_from_MARC(recid) ############## need some code refactoring ############### more_holdings_infos = db.get_holdings_details(recid) borrower_infos = db.get_borrower_details(borrower_id) ######################################################### title_link = create_html_link(CFG_SITE_URL + '/admin/bibcirculation/bibcirculationadmin.py/get_item_details', {'recid': recid}, (book_title)) out = """ This is an automatic email for confirming the hold request for a book on behalf of: %s (email: %s) title: %s author: %s location: %s library: %s publisher: %s year: %s isbn: %s """ % (borrower_infos[1], borrower_infos[2], title_link, book_author, more_holdings_infos[0][1], more_holdings_infos[0][2], book_editor, book_year, book_isbn) return out def get_book_cover(isbn): """ Retrieve book cover using Amazon web services. @param isbn: book's isbn @type isbn: string @return book cover """ from xml.dom import minidom import urllib # connect to AWS cover_xml = urllib.urlopen('http://ecs.amazonaws.com/onca/xml' \ '?Service=AWSECommerceService&AWSAccessKeyId=' \ + CFG_BIBCIRCULATION_AMAZON_ACCESS_KEY + \ '&Operation=ItemSearch&Condition=All&' \ 'ResponseGroup=Images&SearchIndex=Books&' \ 'Keywords=' + isbn) # parse XML try: xml_img = minidom.parse(cover_xml) retrieve_book_cover = xml_img.getElementsByTagName('MediumImage') book_cover = retrieve_book_cover.item(0).firstChild.firstChild.data except AttributeError: book_cover = "%s/img/book_cover_placeholder.gif" % (CFG_SITE_URL) return book_cover def book_information_from_MARC(recid): """ Retrieve book's information from MARC @param recid: identify the record. Primary key of bibrec. @type recid: int @return tuple with title, year, author, isbn and editor. """ book_title = ' '.join(get_fieldvalues(recid, "245__a") + \ get_fieldvalues(recid, "245__b") + \ get_fieldvalues(recid, "245__n") + \ get_fieldvalues(recid, "245__p")) book_year = ' '.join(get_fieldvalues(recid, "260__c")) book_author = ' '.join(get_fieldvalues(recid, "100__a") + \ get_fieldvalues(recid, "100__u")) book_isbn = ' '.join(get_fieldvalues(recid, "020__a")) book_editor = ' , '.join(get_fieldvalues(recid, "260__a") + \ get_fieldvalues(recid, "260__b")) return (book_title, book_year, book_author, book_isbn, book_editor) def book_title_from_MARC(recid): """ Retrieve book's title from MARC @param recid: identify the record. Primary key of bibrec. @type recid: int @return book's title """ book_title = ' '.join(get_fieldvalues(recid, "245__a") + \ get_fieldvalues(recid, "245__b") + \ get_fieldvalues(recid, "245__n") + \ get_fieldvalues(recid, "245__p")) return book_title def update_status_if_expired(loan_id): """ Update the loan's status if status is 'expired'. @param loan_id: identify the loan. Primary key of crcLOAN. @type loan_id: int """ loan_status = db.get_loan_status(loan_id) if loan_status == 'expired': db.update_loan_status('on loan', loan_id) return def get_next_day(date_string): """ Get the next day @param date_string: date @type date_string: string return next day """ # add 1 day more_1_day = datetime.timedelta(days=1) # convert date_string to datetime format tmp_date = time.strptime(date_string, '%Y-%m-%d') # calculate the new date (next day) next_day = datetime.datetime(*tmp_date[:3]) + more_1_day return next_day def generate_new_due_date(days): """ Generate a new due date (today + X days = new due date). @param days: number of days @type days: string @return new due date """ today = datetime.date.today() more_X_days = datetime.timedelta(days=days) tmp_date = today + more_X_days week_day = tmp_date.strftime('%A') due_date = tmp_date.strftime('%Y-%m-%d') due_date_validated = False while not due_date_validated: if week_day in CFG_BIBCIRCULATION_WORKING_DAYS and due_date not in CFG_BIBCIRCULATION_HOLIDAYS: due_date_validated = True else: next_day = get_next_day(due_date) due_date = next_day.strftime('%Y-%m-%d') week_day = next_day.strftime('%A') return due_date def renew_loan_for_X_days(barcode): """ Renew a loan based on its loan period @param barcode: identify the item. Primary key of crcITEM. @type barcode: string @return new due date """ loan_period = db.get_loan_period(barcode) if loan_period == '4 weeks': due_date = generate_new_due_date(30) else: due_date = generate_new_due_date(7) return due_date def make_copy_available(request_id): """ Change the status of a copy for 'available' when an hold request was cancelled. @param request_id: identify the request: Primary key of crcLOANREQUEST @type request_id: int """ barcode_requested = db.get_requested_barcode(request_id) db.update_item_status('available', barcode_requested) return def print_new_loan_information(req, ln): """ Create a printable format with the information of the last loan who has been registered on the table crcLOAN. """ _ = gettext_set_language(ln) # get the last loan from crcLOAN (recid, borrower_id, due_date) = db.get_last_loan() # get book's information (book_title, book_year, book_author, book_isbn, book_editor) = book_information_from_MARC(recid) # get borrower's data/information (name, address, email) (borrower_name, borrower_address, borrower_email) = db.get_borrower_data(borrower_id) # Generate printable format req.content_type = "text/html" req.send_http_header() out = """""" out += """

""" % (CFG_SITE_URL) out += """""" out += """ """ % (_("Loan information")) out += """ """ % (_("This book is sent to you ...")) out += """

%s

%s

""" out += """""" out += """ """ % (_("Title"), book_title, _("Author"), book_author, _("Editor"), book_editor, _("ISBN"), book_isbn, _("Year"), book_year) out += """
%s%s
%s%s
%s%s
%s%s
%s%s

""" out += """""" out += """ """ % (_("Id"), borrower_id, _("Name"), borrower_name, _("Address"), borrower_address, _("Email"), borrower_email) out += """
%s%s
%s%s
%s%s
%s%s

""" out += """""" out += """ """ % (_("Due date"), due_date) out += """

%s: %s

""" out += """
""" req.write("") req.write(out) req.write("") return "\n" def print_pending_hold_requests_information(req, ln): """ Create a printable format with all the information about all pending hold requests. """ _ = gettext_set_language(ln) requests = db.get_pdf_request_data('pending') req.content_type = "text/html" req.send_http_header() out = """""" out += """

""" % (CFG_SITE_URL) out += """""" out += """ """ % (_("List of pending hold requests")) out += """ """ % (time.ctime()) out += """

%s

%s

""" out += """""" out += """ """ % (_("Borrower"), _("Item"), _("Library"), _("Location"), _("From"), _("To"), _("Request date")) for (recid, borrower_name, library_name, location, date_from, date_to, request_date) in requests: out += """ """ % (borrower_name, book_title_from_MARC(recid), library_name, location, date_from, date_to, request_date) out += """
%s %s %s %s %s %s %s
%s %s %s %s %s %s %s


""" req.write("") req.write(out) req.write("") return "\n" def get_item_info_for_search_result(recid): """ Get the item's info from MARC in order to create a search result with more details @param recid: identify the record. Primary key of bibrec. @type recid: int @return book's informations (author, editor and number of copies) """ book_author = ' '.join(get_fieldvalues(recid, "100__a") + \ get_fieldvalues(recid, "100__u")) book_editor = ' , '.join(get_fieldvalues(recid, "260__a") + \ get_fieldvalues(recid, "260__b") + \ get_fieldvalues(recid, "260__c")) book_copies = ' '.join(get_fieldvalues(recid, "964__a")) book_infos = (book_author, book_editor, book_copies) return book_infos def update_request_data(request_id): """ Update the status of a given request. @param request_id: identify the request: Primary key of crcLOANREQUEST @type request_id: int """ barcode = db.get_request_barcode(request_id) nb_requests = db.get_number_requests_per_copy(barcode) is_on_loan = db.is_item_on_loan(barcode) if nb_requests == 0 and is_on_loan is not None: db.update_item_status('on loan', barcode) elif nb_requests == 0 and is_on_loan is None: db.update_item_status('available', barcode) else: db.update_item_status('requested', barcode) return def compare_dates(date): """ Compare given date with today @param date: given date @type date: string @return boolean """ if date < time.strftime("%Y-%m-%d"): return False else: return True def validate_date_format(date): """ Verify the date format @param date: given date @type date: string @return boolean """ try: if time.strptime(date, "%Y-%m-%d"): if compare_dates(date): return True else: return False except ValueError: return False def create_ill_record(book_info): """ Create a new ILL record @param book_info: book's information @type book_info: tuple @return MARC record """ (title, author, place, publisher, year, edition, isbn) = book_info ill_record = """ %(isbn)s %(author)s %(title)s %(edition)s %(place)s %(publisher)s %(year)s ILLBOOK """ % {'isbn': isbn, 'author': author, 'title': title, 'edition': edition, 'place': place, 'publisher': publisher, 'year': year} file_path = '%s/%s_%s.xml' % (CFG_TMPDIR, 'bibcirculation_ill_book', time.strftime("%Y%m%d_%H%M%S")) xml_file = open(file_path, 'w') xml_file.write(ill_record) xml_file.close() # Pass XML file to BibUpload. task_low_level_submission('bibupload', 'bibcirculation', '-P', '5', '-i', file_path) return ill_record def wash_recid_from_ILL_request(ill_request_id): """ Get dictionnary and wash recid values. @param ill_request_id: identify the ILL request. Primray key of crcILLREQUEST @type ill_request_id: int @return recid """ book_info = db.get_ill_book_info(ill_request_id) if looks_like_dictionary(book_info): book_info = eval(book_info) else: book_info = None try: recid = int(book_info['recid']) except KeyError: recid = None return recid def get_list_of_ILL_requests(): """ Get list with all recids related with ILL requests """ list_of_recids = [] ill_requests = db.get_ill_ids() for i in range(len(ill_requests)): recid = wash_recid_from_ILL_request(ill_requests[i][0]) if recid: list_of_recids.append(recid) return list_of_recids def all_copies_are_missing(recid): """ Verify if all copies of an item are missing @param recid: identify the record. Primary key of bibrec @type recid: int @return boolean """ copies_status = db.get_copies_status(recid) number_of_missing = 0 for (status) in copies_status: if status == 'missing': number_of_missing += 1 if number_of_missing == len(copies_status): return True else: return False def has_copies(recid): """ Verify if a recid is item (has copies) @param recid: identify the record. Primary key of bibrec @type recid: int @return boolean """ copies_status = db.get_copies_status(recid) if copies_status is None: return False else: if len(copies_status) == 0: return False else: return True def generate_email_body(template, loan_id): """ Generate the body of an email for loan recalls. @param template: email template @type template: string @param loan_id: identify the loan. Primary key of crcLOAN. @type loan_id: int @return email(body) """ recid = db.get_loan_recid(loan_id) (book_title, book_year, book_author, book_isbn, book_editor) = book_information_from_MARC(int(recid)) out = template % (book_title, book_year, book_author, book_isbn, book_editor) return out def create_item_details_url(recid, ln): """ Generate the URL redirecting to the edition of record copies @param recid: The identifier of the record @type recid: int @param ln: The language identifier @type ln: string @return A string being the URL allowing to edit currently viewed record """ url = '/admin/bibcirculation/bibcirculationadmin.py/get_item_details?ln=%s&recid=%s' % (ln, str(recid)) return CFG_SITE_URL + url def looks_like_dictionary(candidate_string): if re.match(DICC_REGEXP, candidate_string): return True else: return False