def test_fulfill(self): other_client, ignore = IntegrationClient.register( self._db, "http://other_library.org") loan, ignore = create(self._db, Loan, integration_client=other_client, license_pool=self.pool) assert_raises(CannotFulfill, self.shared_collection.fulfill, self.collection, self.client, loan, self.delivery_mechanism) loan.integration_client = self.client # If the API does not return content or a content link, the loan can't be fulfilled. assert_raises(CannotFulfill, self.shared_collection.fulfill, self.collection, self.client, loan, self.delivery_mechanism) eq_([(self.client, loan, self.delivery_mechanism)], self.api.fulfills) self.api.fulfillment = FulfillmentInfo( self.collection, self.pool.data_source.name, self.pool.identifier.type, self.pool.identifier.identifier, "http://content", "text/html", None, None, ) fulfillment = self.shared_collection.fulfill(self.collection, self.client, loan, self.delivery_mechanism) eq_([(self.client, loan, self.delivery_mechanism)], self.api.fulfills[1:]) eq_(self.delivery_mechanism, loan.fulfillment)
def test_fulfill_feed(self): patron = self._patron() work = self._work(with_license_pool=True, with_open_access_download=False) pool = work.license_pools[0] pool.open_access = False streaming_mech = pool.set_delivery_mechanism( DeliveryMechanism.STREAMING_TEXT_CONTENT_TYPE, DeliveryMechanism.OVERDRIVE_DRM, RightsStatus.IN_COPYRIGHT, None) now = datetime.datetime.utcnow() loan, ignore = pool.loan_to(patron, start=now) fulfillment = FulfillmentInfo( pool.collection, pool.data_source.name, pool.identifier.type, pool.identifier.identifier, "http://streaming_link", Representation.TEXT_HTML_MEDIA_TYPE + DeliveryMechanism.STREAMING_PROFILE, None, None) feed_obj = CirculationManagerLoanAndHoldAnnotator.single_fulfillment_feed( None, loan, fulfillment, test_mode=True) raw = etree.tostring(feed_obj) entries = feedparser.parse(raw)['entries'] eq_(1, len(entries)) links = entries[0]['links'] # The feed for a single fulfillment only includes one fulfill link. fulfill_links = [ link for link in links if link['rel'] == "http://opds-spec.org/acquisition" ] eq_(1, len(fulfill_links)) eq_( Representation.TEXT_HTML_MEDIA_TYPE + DeliveryMechanism.STREAMING_PROFILE, fulfill_links[0]['type']) eq_("http://streaming_link", fulfill_links[0]['href'])
def fulfill( self, patron, pin, licensepool, internal_format=None, part=None, fulfill_part_url=None, ): """Fulfill the loan. NOTE: This method requires the patron to have either: - an active ProQuest JWT bearer token - or a SAML affiliation ID which will be used to create a new ProQuest JWT bearer token. """ self._logger.info("Started fulfilling '{0}' for patron {1}".format( internal_format, patron)) try: with self._get_configuration(self._db) as configuration: token = self._get_or_create_proquest_token( patron, configuration) book = self._get_book(patron, configuration, licensepool.identifier.identifier) if book.content is not None: fulfillment_info = FulfillmentInfo( licensepool.collection, licensepool.data_source.name, licensepool.identifier.type, licensepool.identifier.identifier, content_link=None, content_type=book.content_type if book.content_type else internal_format.delivery_mechanism.content_type, content=book.content, content_expires=None, ) else: now = utc_now() expires_in = (token.expires - now).total_seconds() token_document = dict( token_type="Bearer", access_token=token.credential, expires_in=expires_in, location=book.link, ) return FulfillmentInfo( licensepool.collection, licensepool.data_source.name, licensepool.identifier.type, licensepool.identifier.identifier, content_link=None, content_type=DeliveryMechanism.BEARER_TOKEN, content=json.dumps(token_document), content_expires=token.expires, ) self._logger.info( "Finished fulfilling {0} for patron {1}: {2}".format( internal_format, patron, fulfillment_info)) return fulfillment_info except BaseError as exception: self._logger.exception("Failed to fulfill out {0} for patron {1}") raise CannotFulfill(str(exception))