text: #!/usr/bin/env python3
  
  from __future__ import print_function
  from datetime import datetime
  from botocore.exceptions import ClientError
  import boto3
  import pandas as pd
  import logging
  import os
  import json
  
  logger = logging.getLogger()
  logger.setLevel(logging.INFO)
  
  OUTPUT_QUEUE = os.getenv("OUTPUT_QUEUE")
  
  
  def send_sqs_message(queue_url, msg):
      sqs_client = boto3.client('sqs')
  
      try:
          sqs_client.send_message(QueueUrl=queue_url,
                                  MessageBody=json.dumps(msg))
      except ClientError as e:
          print(e.response['Error']['Message'])
  
      return
  
  
  def lambda_handler(event, context):
  
      # Create S3 client.
      s3_client = boto3.client('s3')
  
      # Read messages from SQS.
      for record in event['Records']:
  
          payload = json.loads(record['body'])['Records'][0]
  
          # Calculate today's date.
          today = datetime.now().strftime('%Y%m%d')
  
          # Extract bucket name.
          bucket = payload['s3']['bucket']['name']
  
          # Construct expected keys.
          files = {}
          types = ['clients', 'portfolios', 'accounts', 'transactions']
          for key in types:
              files[key] = "{}_{}.csv".format(key, today)
  
          # Fetch objects from s3.
          objects = {}
          for key in types:
              objects[key] = s3_client.get_object(Bucket=bucket, Key=files[key])
  
          # Read data for each type.
          data = {}
          for key in types:
              data[key] = pd.read_csv(objects[key]['Body'])
  
          # Create dataframes from CSVs.
          ref_data = pd.merge(data['clients'],
                              data['portfolios'],
                              on='client_reference')
          linked_data = pd.merge(ref_data,
                                 data['accounts'],
                                 on='accout_number')
          final_data = pd.merge(linked_data,
                                data['transactions'],
                                on='accout_number')
  
          # Generate dictionaries from dataframes.
          linked_data_dict = linked_data.to_dict('records')
          final_data_dict = final_data.to_dict('records')
  
          # Create client messages.
          for client in linked_data_dict:
              client_msg = {}
              client_msg['type'] = 'client_message'
              client_msg['client_reference'] = client['client_reference']
              client_msg['tax_free_allowance'] = client['tax_free_allowance']
              client_msg['taxes_paid'] = client['taxes_paid']
              send_sqs_message(OUTPUT_QUEUE, client_msg)
  
          # Create portfolio messages.
          for folio in linked_data_dict:
              portfolio_msg = {}
              portfolio_msg['type'] = 'portfolio_message'
              portfolio_msg['portfolio_reference'] = folio['portfolio_reference']
              portfolio_msg['cash_balance'] = folio['cash_balance']
              portfolio_msg['number_of_transactions'] = sum(
                  [1 for n in final_data_dict
                   if n['portfolio_reference'] == folio['portfolio_reference']])
              portfolio_msg['sum_of_deposits'] = sum(
                  [n['amount'] for n in final_data_dict
                   if (n['portfolio_reference'] == folio['portfolio_reference']
                   and n['keyword'] == 'DEPOSIT')])
              send_sqs_message(OUTPUT_QUEUE, portfolio_msg)
  
      return
  