# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT-0 # # Permission is hereby granted, free of charge, to any person obtaining a copy of this # software and associated documentation files (the "Software"), to deal in the Software # without restriction, including without limitation the rights to use, copy, modify, # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # This code expects that you have AWS credentials setup per: # https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html from logging import basicConfig, getLogger, INFO from pyqldbsamples.add_secondary_owner import get_document_ids, print_result, SampleData from pyqldbsamples.constants import Constants from pyqldbsamples.model.sample_data import convert_object_to_ion from pyqldbsamples.connect_to_ledger import create_qldb_driver logger = getLogger(__name__) basicConfig(level=INFO) def find_person_from_document_id(transaction_executor, document_id): """ Query a driver's information using the given ID. :type transaction_executor: :py:class:`pyqldb.execution.executor.Executor` :param transaction_executor: An Executor object allowing for execution of statements within a transaction. :type document_id: :py:class:`amazon.ion.simple_types.IonPyText` :param document_id: The document ID required to query for the person. :rtype: :py:class:`amazon.ion.simple_types.IonPyDict` :return: The resulting document from the query. """ query = 'SELECT p.* FROM Person AS p BY pid WHERE pid = ?' cursor = transaction_executor.execute_statement(query, document_id) return next(cursor) def find_primary_owner_for_vehicle(driver, vin): """ Find the primary owner of a vehicle given its VIN. :type driver: :py:class:`pyqldb.driver.qldb_driver.QldbDriver` :param driver: An instance of the QldbDriver class. :type vin: str :param vin: The VIN to find primary owner for. :rtype: :py:class:`amazon.ion.simple_types.IonPyDict` :return: The resulting document from the query. """ logger.info('Finding primary owner for vehicle with VIN: {}.'.format(vin)) query = "SELECT Owners.PrimaryOwner.PersonId FROM VehicleRegistration AS v WHERE v.VIN = ?" cursor = driver.execute_lambda(lambda executor: executor.execute_statement(query, convert_object_to_ion(vin))) try: return driver.execute_lambda(lambda executor: find_person_from_document_id(executor, next(cursor).get('PersonId'))) except StopIteration: logger.error('No primary owner registered for this vehicle.') return None def update_vehicle_registration(driver, vin, document_id): """ Update the primary owner for a vehicle using the given VIN. :type driver: :py:class:`pyqldb.driver.qldb_driver.QldbDriver` :param driver: An instance of the QldbDriver class. :type vin: str :param vin: The VIN for the vehicle to operate on. :type document_id: :py:class:`amazon.ion.simple_types.IonPyText` :param document_id: New PersonId for the primary owner. :raises RuntimeError: If no vehicle registration was found using the given document ID and VIN. """ logger.info('Updating the primary owner for vehicle with Vin: {}...'.format(vin)) statement = "UPDATE VehicleRegistration AS r SET r.Owners.PrimaryOwner.PersonId = ? WHERE r.VIN = ?" cursor = driver.execute_lambda(lambda executor: executor.execute_statement(statement, document_id, convert_object_to_ion(vin))) try: print_result(cursor) logger.info('Successfully transferred vehicle with VIN: {} to new owner.'.format(vin)) except StopIteration: raise RuntimeError('Unable to transfer vehicle, could not find registration.') def validate_and_update_registration(driver, vin, current_owner, new_owner): """ Validate the current owner of the given vehicle and transfer its ownership to a new owner. :type driver: :py:class:`pyqldb.driver.qldb_driver.QldbDriver` :param driver: An instance of the QldbDriver class. :type vin: str :param vin: The VIN of the vehicle to transfer ownership of. :type current_owner: str :param current_owner: The GovId of the current owner of the vehicle. :type new_owner: str :param new_owner: The GovId of the new owner of the vehicle. :raises RuntimeError: If unable to verify primary owner. """ primary_owner = find_primary_owner_for_vehicle(driver, vin) if primary_owner is None or primary_owner['GovId'] != current_owner: raise RuntimeError('Incorrect primary owner identified for vehicle, unable to transfer.') document_ids = driver.execute_lambda(lambda executor: get_document_ids(executor, Constants.PERSON_TABLE_NAME, 'GovId', new_owner)) update_vehicle_registration(driver, vin, document_ids[0]) def main(ledger_name=Constants.LEDGER_NAME): """ Find primary owner for a particular vehicle's VIN. Transfer to another primary owner for a particular vehicle's VIN. """ vehicle_vin = SampleData.VEHICLE[0]['VIN'] previous_owner = SampleData.PERSON[0]['GovId'] new_owner = SampleData.PERSON[1]['GovId'] try: with create_qldb_driver(ledger_name) as driver: validate_and_update_registration(driver, vehicle_vin, previous_owner, new_owner) except Exception as e: logger.exception('Error updating VehicleRegistration.') raise e if __name__ == '__main__': main()