def lease_execute(id): """Execute using the lease_esignature_id as there could be more than one.""" request = app.current_request user_id = request.context["authorizer"]["principalId"] # Validate the json request try: execute_data = ExecuteSchema().load(request.json_body) except ValidationError as err: return gzip_response(data={ "success": False, "errors": err.messages }, status_code=200) db = DatabaseConnection() session = db.session() query = session.query(LeaseEsignature).join("lease") lease_esignature = (query.filter(LeaseEsignature.id == id).filter( Lease.user_id == user_id).first()) # Make sure the corresponding item exists in the database if not lease_esignature: return gzip_response(data={"message": "Not Found"}, status_code=404) bm_api = BluemoonApi(token=get_token(request=request)) # Update the status just in case we did not receive the latest data response = bm_api.esignature_details(bm_id=lease_esignature.bluemoon_id) if not response: return api_error_response() storage_data = response["data"] lease_esignature.data = storage_data try: signers_data = storage_data["esign"]["data"]["signers"]["data"] lease_esignature.transition_status(signers_data=signers_data) except KeyError: pass session.add(lease_esignature) session.commit() # End status update check # Verify we can execute the document if lease_esignature.status != StatusEnum.signed: data = { "success": False, "errors": [{ "status": "Lease has not been signed by all residents." }], } return gzip_response(data=data, status_code=404) # Execute the document response = bm_api.execute_lease(bm_id=lease_esignature.bluemoon_id, data=execute_data) # TODO: Add url to Bluemoon response and return value. success = "executed" in response and response["executed"] return gzip_response(data={"success": success}, status_code=200)
def lease_print(id): """Print requires the lease_id as it just uses that data, no esignature request.""" user_id = app.current_request.context["authorizer"]["principalId"] db = DatabaseConnection() session = db.session() query = session.query(Lease) lease = query.filter(Lease.id == id).filter( Lease.user_id == user_id).first() if not lease: return gzip_response(data={"message": "Not Found"}, status_code=404) if not lease.bluemoon_id: return gzip_response(data={"message": "Bluemoon Lease not created."}, status_code=200) data = app.current_request.json_body token = get_token(request=app.current_request) selected_forms = data.get("forms") try: forms = forms_mapper(selected_forms=selected_forms, token=token) except MissingLeaseFormsException: return api_error_response() post_data = {"lease_id": lease.bluemoon_id, "data": forms} bm_api = BluemoonApi(token=token) response = bm_api.post_raw(path="lease/generate/pdf", data=post_data) content_type = response.headers.get("Content-Type") context = {} if content_type == "application/pdf": length = 0 mem = io.BytesIO() for chunk in response.iter_content(chunk_size=128): length += len(chunk) mem.write(chunk) mem.seek(0) now = datetime.datetime.now() file_name = "{0:%d}/{0:%m}/{1}.pdf".format(now, uuid.uuid4().hex) s3_client.upload_fileobj(mem, BUCKET, file_name) signed_url = s3_client.generate_presigned_url( ClientMethod="get_object", Params={ "Bucket": BUCKET, "Key": file_name }, ExpiresIn=3600, ) context["success"] = True context["url"] = signed_url elif content_type == "application/json": context.update(response.json()) return gzip_response(data=context, status_code=200)
def leases(): """Filters and returns list of leases or units, this is local app data.""" request = app.current_request user_id = request.context["authorizer"]["principalId"] db = DatabaseConnection() session = db.session() if request.method == "POST": try: lease_data = request.json_body new_lease = LeaseSchema().load(lease_data, session=session) except ValidationError as err: return {"success": False, "errors": err.messages} else: new_lease.user_id = user_id session.add(new_lease) session.commit() filters = { "fields": ["id", "bluemoon_id", "unit_number"], "default_page_size": 25, "default_order": "id", "default_dir": "desc", } filtering = ModelFilter(model=Lease, filters=filters, user_id=user_id, params=request.query_params) results = filtering.results() schema = PaginatedLeaseSchema() return gzip_response(data=schema.dump(results), status_code=200)
def configuration(id): """Fetch the configuration for Bluemoon integration.""" user_id = app.current_request.context["authorizer"]["principalId"] db = DatabaseConnection() session = db.session() query = session.query(Lease) lease = query.filter(Lease.id == id).filter( Lease.user_id == user_id).first() token = get_token(request=app.current_request) bm_api = BluemoonApi(token=token) # Configuration object for lease-editor. Passing in some basic data along with # a generated callback url configuration = { "apiUrl": bm_api.url, "propertyNumber": bm_api.property_number(), "accessToken": token, "view": "create", "callBack": "{}/lease/callback/{}".format(os.getenv("UNITS_URL_EXTERNAL"), lease.id), "leaseData": { "standard": { "address": "123 Super Dr.", "unit_number": lease.unit_number } }, } return gzip_response(data=configuration, status_code=200)
def lease_forms(): bm_api = BluemoonApi(token=get_token(request=app.current_request)) lease_forms = bm_api.lease_forms() if not lease_forms: return api_error_response() response = {"data": lease_forms} return gzip_response(data=response, status_code=200)
def fetch_esignature_document(id): """Fetch the complete lease document with receipt""" app.log.debug("here") user_id = app.current_request.context["authorizer"]["principalId"] token = get_token(request=app.current_request) db = DatabaseConnection() session = db.session() query = session.query(LeaseEsignature).join("lease") lease_esignature = (query.filter(LeaseEsignature.id == id).filter( Lease.user_id == user_id).first()) if not lease_esignature: return gzip_response(data={"message": "Not Found"}, status_code=404) bm_api = BluemoonApi(token=token) response = bm_api.get_raw( path="esignature/lease/pdf/{}".format(lease_esignature.bluemoon_id)) content_type = response.headers.get("Content-Type") context = {} if content_type == "application/pdf": length = 0 mem = io.BytesIO() for chunk in response.iter_content(chunk_size=128): length += len(chunk) mem.write(chunk) mem.seek(0) now = datetime.datetime.now() file_name = "{0:%d}/{0:%m}/{1}.pdf".format(now, uuid.uuid4().hex) s3_client.upload_fileobj(mem, BUCKET, file_name) signed_url = s3_client.generate_presigned_url( ClientMethod="get_object", Params={ "Bucket": BUCKET, "Key": file_name }, ExpiresIn=3600, ) context["success"] = True context["url"] = signed_url elif content_type == "application/json": context.update(response.json()) return gzip_response(data=context, status_code=200)
def lease_request_esign(id): request = app.current_request user_id = request.context["authorizer"]["principalId"] db = DatabaseConnection() session = db.session() query = session.query(Lease) lease = query.filter(Lease.id == id).filter( Lease.user_id == user_id).first() if not lease: return gzip_response(data={"message": "Not Found"}, status_code=404) data = app.current_request.json_body token = get_token(request=app.current_request) selected_forms = data.get("forms") try: forms = forms_mapper(selected_forms=selected_forms, token=token) except MissingLeaseFormsException: return api_error_response() bm_api = BluemoonApi(token=token) post_data = { "lease_id": lease.bluemoon_id, "external_id": lease.id, "send_notifications": True, "notification_url": "{}/{}".format(os.getenv("UNITS_URL"), "notifications"), "data": forms, } response = bm_api.request_esignature(data=post_data) if not response.get("success"): return gzip_response(data=response, status_code=200) lease_esignature = LeaseEsignature( lease_id=lease.id, bluemoon_id=response["data"]["id"], data=response["data"]["data"], ) session.add(lease_esignature) session.commit() return gzip_response(data=LeaseEsignatureSchema().dump(lease_esignature), status_code=201)
def lease_callback(id): """Fetches lease and handles the callback.""" # This endpoint receives the AJAX request from the lease-editor request = app.current_request db = DatabaseConnection() session = db.session() query = session.query(Lease) lease = query.filter(Lease.id == id).first() if not lease: return gzip_response(data={"message": "Not Found"}, status_code=404) # The request body contains the full lease object but I only care about # the lease id if request.method == "POST" and "id" in request.json_body: lease.bluemoon_id = request.json_body["id"] session.add(lease) session.commit() return gzip_response(data=LeaseSchema().dump(lease), status_code=200)
def lease(id): """Fetches lease unit and handles updates.""" request = app.current_request user_id = request.context["authorizer"]["principalId"] db = DatabaseConnection() session = db.session() query = session.query(Lease) lease = query.filter(Lease.id == id).filter( Lease.user_id == user_id).first() if not lease: return gzip_response(data={"message": "Not Found"}, status_code=404) if request.method == "POST" and "id" in request.json_body: # Currently there is no update available app.log.info("update lease") # session.add(lease) # session.commit() return gzip_response(data=LeaseSchema().dump(lease), status_code=200)
def notifications(): """Lease Esignature Requests notifications from Bluemoon.""" data = app.current_request.json_body # Verify the data fits the minimum standars if "id" not in data: return gzip_response(data={"message": "Bad Request"}, status_code=405) db = DatabaseConnection() session = db.session() query = session.query(LeaseEsignature) lease_esignature = query.filter( LeaseEsignature.bluemoon_id == data["id"]).first() lease_esignature.data = data try: # The data is a bit nested, but ideally Bluemoon API will pass a document status soon signers_data = data["esign"]["data"]["signers"]["data"] lease_esignature.transition_status(signers_data=signers_data) except KeyError: pass session.add(lease_esignature) session.commit() return {"success": True}