AWSTemplateFormatVersion: 2010-09-09
Description: "Amazon Connect Callback Request"
# Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# 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.
Mappings:
  FunctionMap:
    Configuration:
      S3KeyLambda: Lambda/
      S3KeyLambdalayer: Lambdalayer/
      S3KeyLex: Lex/
      SolutionID: CBREQ0001
Parameters:
  instanceId:
    Type: String
    Description: >-
      The instance id of the Amazon Connect instance that the customer will
      interact with while chatting. You can find this in the Amazon Connect
      console when viewing your instance details.
    AllowedPattern: '\w{8}-\w{4}-\w{4}-\w{4}-\w{12}'
  helperPhoneNumber:
    Type: String
    Description: >-
      The phone number assigned to the Connect instance from which the queued
      callback will be triggered. Must be in E164 format (with the '+' prefix)
  queueId:
      Type: String
      Description: >-
        The queue id of the Amazon Connect Basic queue the callback will be queued in.
        Note: You can change this queue after the deployment to meet your needs.
      AllowedPattern: '\w{8}-\w{4}-\w{4}-\w{4}-\w{12}'
  LogLevel:
    Type: String
    Description: >-
      Set Lambda Log Level. Possible values : 'INFO', 'ERROR'. Default is ERROR.
    Default: ERROR
Resources:
  callbackblogartifacts:
    Type: AWS::S3::Bucket
    DeletionPolicy: Delete
    UpdateReplacePolicy: Retain
    Properties:
      BucketEncryption: 
        ServerSideEncryptionConfiguration: 
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
  CopyArtifactsLambdaIamRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - 's3:PutObject'
                Resource: !Sub 'arn:aws:s3:::${callbackblogartifacts}/*'
              - Effect: Allow
                Action:
                  - 's3:GetObject'
                  - 's3:GetObjectVersion'
                Resource: !Sub 'arn:aws:s3:::aws-contact-center-blog/*'
              - Effect: Allow
                Action:
                  - 's3:ListBucket'
                  - 's3:ListBucketVersions'
                Resource: 
                  - !Sub 'arn:aws:s3:::aws-contact-center-blog/*'
                  - !Sub 'arn:aws:s3:::${callbackblogartifacts}/*'
              - Effect: Allow
                Action:
                  - 's3:DeleteObject'
                Resource: 
                  - !Sub 'arn:aws:s3:::${callbackblogartifacts}/*'
      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
  CustomResourceCopySourceFunction:
      Type: 'AWS::Lambda::Function'
      Properties:
        Role: !GetAtt CopyArtifactsLambdaIamRole.Arn
        Handler: "index.handler"
        Runtime: "nodejs16.x"
        Code:
          ZipFile: |
            // Copyright 2022 Amazon.com and its affiliates; all rights reserved. This file is Amazon Web Services Content and may not be duplicated or distributed without permission.
            const s3 = new (require('aws-sdk')).S3();
            const response = require('cfn-response');
            const sourceBucket = 'aws-contact-center-blog';
            const sourcePrefix = 'callback-blog-artifacts';
            const sourceObjectArray = [
              'Lambdalayer/pytz2022mod.zip',
              'Lambda/cb-abort-sfn.zip',
              'Lambda/cb-add-additional-day-availability-slots.zip',
              'Lambda/cb-add-lambdas-to-connect.zip',
              'Lambda/cb-associate-lex-bot.zip',
              'Lambda/cb-create-availability-slot-data.zip',
              'Lambda/cb-get-first-available-slot.zip',
              'Lambda/cb-get-hoo-from-connect-api.zip',
              'Lambda/cb-increment-availability-slot.zip',
              'Lambda/cb-place-callback-request.zip',
              'Lambda/cb-place-outbound-call.zip',
              'Lambda/cb-process-requested-date-time.zip',
              'Lex/CallBackRequestLexV2.zip'
            ];
            exports.handler = async (event, context) => {
                var result = {responseStatus: 'FAILED', responseData: {Data: 'Never updated'}};
                try {
                    console.log(`Received event with type ${event.RequestType}`); 
                    if(event.RequestType === 'Create' || event.RequestType === 'Update') {
                        copyResult = await Promise.all(
                            sourceObjectArray.map( async (object) => {
                                s3Result = await s3.copyObject({
                                    Bucket: event.ResourceProperties.callbackblogartifacts,
                                    Key: object,
                                    CopySource: `${sourceBucket}/${sourcePrefix}/${object}`
                                }).promise();
                                console.log(`Finished uploading File with result ${JSON.stringify(s3Result, 0, 4)}`);
                            }),
                        );
                        result.responseStatus = 'SUCCESS';
                        result.responseData['Data'] = 'Successfully uploaded files';
                    } else if (event.RequestType === 'Delete') {
                        cleanupResult = await Promise.all(
                            sourceObjectArray.map( async (object) => {
                                s3Result = await s3.deleteObjects({
                                    Bucket: event.ResourceProperties.callbackblogartifacts,
                                    Delete: { Objects: [{Key: object }]}
                                }).promise();
                                console.log(`Finished deleting files with result ${JSON.stringify(s3Result, 0, 4)}`);
                            }),
                        );                        
                        result.responseStatus = 'SUCCESS',
                        result.responseData['Data'] = 'Successfully deleted files';
                    }
                } catch (error) {
                    console.log(JSON.stringify(error, 0, 4));
                    result.responseStatus = 'FAILED';
                    result.responseData['Data'] = 'Failed to process event';
                } finally {
                    return await responsePromise(event, context, result.responseStatus, result.responseData, `mainstack`);
                }
            };
            function responsePromise(event, context, responseStatus, responseData, physicalResourceId) {
                return new Promise(() => response.send(event, context, responseStatus, responseData, physicalResourceId));
            }
        Timeout: 50
  CopyCfnStacksLambdaTrigger:
    Type: 'Custom::CopyCfnStacksLambdaTrigger'
    Properties:
      ServiceToken: !GetAtt CustomResourceCopySourceFunction.Arn
      callbackblogartifacts: !Ref callbackblogartifacts
    DependsOn:
      - CustomResourceCopySourceFunction
  ACBlogCallbackHelperFlow:
    Type: 'AWS::Connect::ContactFlow'
    Properties:
      Name: AC-Blog-Callback-Helper
      Description: Flow used to meet with StartOutboundVoiceContact API requirement. No relevance for customer experience
      InstanceArn:
        !Join
          - ''
          - - 'arn:aws:connect:'
            - !Ref AWS::Region
            - ':'
            - !Ref AWS::AccountId
            - ':'
            - 'instance/'
            - !Ref instanceId
      Content: "{\"Version\":\"2019-10-30\",\"StartAction\":\"d7ecf9f0-7fdf-44dd-9fab-010ffa91280e\",\"Metadata\":{\"entryPointPosition\":{\"x\":15,\"y\":18},\"snapToGrid\":false,\"ActionMetadata\":{\"8d6e2373-75b2-4791-8b5a-f534fd8f0c5c\":{\"position\":{\"x\":685,\"y\":46}},\"d7ecf9f0-7fdf-44dd-9fab-010ffa91280e\":{\"position\":{\"x\":175,\"y\":25}},\"73380722-6d43-43b9-be7b-2f82215dc708\":{\"position\":{\"x\":427,\"y\":23},\"useDynamic\":false}}},\"Actions\":[{\"Identifier\":\"8d6e2373-75b2-4791-8b5a-f534fd8f0c5c\",\"Type\":\"DisconnectParticipant\",\"Parameters\":{},\"Transitions\":{}},{\"Identifier\":\"d7ecf9f0-7fdf-44dd-9fab-010ffa91280e\",\"Parameters\":{\"FlowLoggingBehavior\":\"Enabled\"},\"Transitions\":{\"NextAction\":\"73380722-6d43-43b9-be7b-2f82215dc708\",\"Errors\":[],\"Conditions\":[]},\"Type\":\"UpdateFlowLoggingBehavior\"},{\"Identifier\":\"73380722-6d43-43b9-be7b-2f82215dc708\",\"Parameters\":{\"SSML\":\"<speak><break time=\\\"5s\\\"/></speak>\"},\"Transitions\":{\"NextAction\":\"8d6e2373-75b2-4791-8b5a-f534fd8f0c5c\",\"Errors\":[{\"NextAction\":\"8d6e2373-75b2-4791-8b5a-f534fd8f0c5c\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"MessageParticipant\"}]}"
      State: ACTIVE
      Type: CONTACT_FLOW
  ACBlogCallbackPlacingFlow:
    Type: 'AWS::Connect::ContactFlow'
    Properties:
      Name: AC-Blog-Callback-Placing
      Description: Create Queue callback in Amazon Connect to support the agent first strategy before placing the outbound call
      InstanceArn:
        !Join
          - ''
          - - 'arn:aws:connect:'
            - !Ref AWS::Region
            - ':'
            - !Ref AWS::AccountId
            - ':'
            - 'instance/'
            - !Ref instanceId
      Content: !Sub
        - "{\"Version\":\"2019-10-30\",\"StartAction\":\"479efbe4-4a04-47c0-a9ad-84d708b85981\",\"Metadata\":{\"entryPointPosition\":{\"x\":15,\"y\":20},\"snapToGrid\":false,\"ActionMetadata\":{\"b2db8b85-e90b-4ac3-8997-c315df672db7\":{\"position\":{\"x\":939,\"y\":15},\"useDynamic\":false},\"b2d12972-7232-404a-9b11-8cd8a3d2cc4d\":{\"position\":{\"x\":684,\"y\":14},\"useDynamic\":false,\"queue\":{\"id\":\"${BASICQUEUEID}\",\"text\":\"BasicQueue\"}},\"d1c20f41-16cb-4cbe-8751-1fcce04617f6\":{\"position\":{\"x\":1235,\"y\":177}},\"479efbe4-4a04-47c0-a9ad-84d708b85981\":{\"position\":{\"x\":170,\"y\":49}},\"70bd5129-4689-44cc-a6b5-a918d15fb289\":{\"position\":{\"x\":409,\"y\": 53}}}},\"Actions\":[{\"Identifier\":\"b2db8b85-e90b-4ac3-8997-c315df672db7\",\"Parameters\":{\"InitialCallDelaySeconds\": \"5\",\"MaximumConnectionAttempts\": \"2\",\"RetryDelaySeconds\":\"300\"},\"Transitions\":{\"NextAction\":\"d1c20f41-16cb-4cbe-8751-1fcce04617f6\",\"Errors\":[{\"NextAction\":\"d1c20f41-16cb-4cbe-8751-1fcce04617f6\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"CreateCallbackContact\"},{\"Identifier\":\"b2d12972-7232-404a-9b11-8cd8a3d2cc4d\",\"Parameters\":{\"QueueId\":\"${BASICQUEUEID}\"},\"Transitions\":{\"NextAction\":\"b2db8b85-e90b-4ac3-8997-c315df672db7\",\"Errors\":[{\"NextAction\": \"b2db8b85-e90b-4ac3-8997-c315df672db7\",\"ErrorType\": \"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"UpdateContactTargetQueue\"},{\"Identifier\":\"d1c20f41-16cb-4cbe-8751-1fcce04617f6\",\"Type\":\"DisconnectParticipant\",\"Parameters\":{},\"Transitions\":{}},{\"Identifier\":\"479efbe4-4a04-47c0-a9ad-84d708b85981\",\"Parameters\":{\"FlowLoggingBehavior\":\"Enabled\"},\"Transitions\":{\"NextAction\":\"70bd5129-4689-44cc-a6b5-a918d15fb289\",\"Errors\":[],\"Conditions\":[]},\"Type\": \"UpdateFlowLoggingBehavior\"},{\"Identifier\":\"70bd5129-4689-44cc-a6b5-a918d15fb289\",\"Parameters\":{\"CallbackNumber\":\"$.Attributes.CustomerEndpointAddress\"},\"Transitions\":{\"NextAction\":\"b2d12972-7232-404a-9b11-8cd8a3d2cc4d\",\"Errors\":[{\"NextAction\":\"d1c20f41-16cb-4cbe-8751-1fcce04617f6\",\"ErrorType\":\"InvalidCallbackNumber\"},{\"NextAction\":\"d1c20f41-16cb-4cbe-8751-1fcce04617f6\",\"ErrorType\":\"CallbackNumberNotDialable\"}],\"Conditions\":[]},\"Type\":\"UpdateContactCallbackNumber\"}]}"
        - BASICQUEUEID:
            !Join
              - ''
              - - 'arn:aws:connect:'
                - !Ref AWS::Region
                - ':'
                - !Ref AWS::AccountId
                - ':'
                - 'instance/'
                - !Ref instanceId
                - '/queue/'
                - !Ref queueId      
      State: ACTIVE
      Type: CONTACT_FLOW
  ACBlogCallbackWelcomeFlow:
    Type: 'AWS::Connect::ContactFlow'
    Properties:
      Name: AC-Blog-Callback-Welcome
      Description: Provides customer experience while leaving the callback
      InstanceArn:
        !Join
          - ''
          - - 'arn:aws:connect:'
            - !Ref AWS::Region
            - ':'
            - !Ref AWS::AccountId
            - ':'
            - 'instance/'
            - !Ref instanceId
      State: ACTIVE
      Content: "{\"Version\":\"2019-10-30\",\"StartAction\":\"e8b74e72-86f8-4966-b521-b3a6d86492b4\",\"Metadata\":{\"entryPointPosition\":{\"x\":15,\"y\":343},\"snapToGrid\":false,\"ActionMetadata\":{\"db9a362d-aa42-4f99-86ad-4d9e17a5aa43\":{\"position\":{\"x\":1612,\"y\":585}},\"84412a25-4f1f-4f8a-800f-72b5827115a0\":{\"position\":{\"x\":2142,\"y\":779},\"useDynamic\":false},\"8bed348e-ecb5-47f2-b0bd-a6c074ba579e\":{\"position\":{\"x\":684,\"y\":307},\"useDynamic\":false},\"e8b74e72-86f8-4966-b521-b3a6d86492b4\":{\"position\":{\"x\":185,\"y\":333}},\"b14e28e7-b410-4ee2-becc-bc10d4f34f23\":{\"position\":{\"x\":3272,\"y\":193},\"useDynamic\":false},\"db50269f-9fce-4fdc-bbee-40f7fa8a8dbb\":{\"position\":{\"x\":1860,\"y\":889},\"conditionMetadata\":[{\"operator\":{\"name\":\"Equals\",\"value\":\"Equals\",\"shortDisplay\":\"=\"},\"value\":\"out_of_hours\",\"id\":\"c3e3c419-dbc2-487e-ba90-402a1fa1ba9c\"},{\"operator\":{\"name\":\"Equals\",\"value\":\"Equals\",\"shortDisplay\":\"=\"},\"value\":\"out_of_allowed_day_in_advanced\",\"id\":\"6631313c-669c-4e66-80df-fa33d4244b59\"},{\"operator\":{\"name\":\"Equals\",\"value\":\"Equals\",\"shortDisplay\":\"=\"},\"value\":\"past_time_requested\",\"id\":\"d958cc52-5f84-4379-8399-b72e29926950\"},{\"operator\":{\"name\":\"Equals\",\"value\":\"Equals\",\"shortDisplay\":\"=\"},\"value\":\"slots_available\",\"id\":\"13ea0266-1049-489f-b95f-ef0f5fac771c\"},{\"operator\":{\"name\":\"Equals\",\"value\":\"Equals\",\"shortDisplay\":\"=\"},\"value\":\"no_slots_available\",\"id\":\"16854ba8-7e1f-4ca5-86ad-5f699c54a6c7\"}]},\"ffabc50b-8843-49bd-bbd4-943977bdeccf\":{\"position\":{\"x\":3041,\"y\":194},\"conditionMetadata\":[{\"operator\":{\"name\":\"Equals\",\"value\":\"Equals\",\"shortDisplay\":\"=\"},\"value\":\"true\",\"id\":\"0ced08fa-14dd-4b01-8620-9714c337d72a\"}]},\"a932ed28-7977-47b6-99b4-beebd739625b\":{\"position\":{\"x\":1596,\"y\":293},\"dynamicParams\":[\"SFNExecutionARN\"]},\"6e306611-08f3-4a65-be63-e69740f237ea\":{\"position\":{\"x\":1389,\"y\":510},\"useDynamic\":false},\"eaa02efa-540a-49d8-bd63-6b538af959eb\":{\"position\":{\"x\":918,\"y\":297},\"dynamicParams\":[\"callBackDate\",\"callBackTime\"]},\"1ec9f841-ddba-48a8-96a8-12bf120ffa13\":{\"position\":{\"x\":1151,\"y\":296},\"dynamicMetadata\":{\"callBackDate\":true,\"callBackTime\":true,\"CallBackConfirmation\":false,\"HOONAME\":false},\"useDynamic\":false},\"50935c43-2a1d-4536-af3c-a16b1ac34fae\":{\"position\":{\"x\":2799,\"y\":199},\"dynamicParams\":[\"callBackDate\",\"SFNExecutionARN\",\"callBackTime\",\"SLOT_AVAILABLE\",\"Available_Slot\"]},\"dc303b42-b3ce-4de8-aff9-4ddd2c72e895\":{\"position\":{\"x\":2797,\"y\":399},\"useDynamic\":false},\"292cebba-a8ea-4e88-9fbb-a9f5dff768dc\":{\"position\":{\"x\":675,\"y\":15},\"useDynamic\":false},\"9e1e0ec1-e3bf-4510-abd7-ebba28e34cef\":{\"position\":{\"x\":2084,\"y\":184},\"useDynamic\":false},\"47cd3918-e1f6-4635-8f94-30af4596c81f\":{\"position\":{\"x\":2099,\"y\":383},\"useDynamic\":false},\"d70c3a2d-a2ca-4383-88b3-d3cff11fc72d\":{\"position\":{\"x\":2118,\"y\":584},\"useDynamic\":false},\"7db7f1c2-46fc-4aaf-a984-3163024e5356\":{\"position\":{\"x\":2157,\"y\":992},\"useDynamic\":false},\"02fa6720-0f9d-4490-a409-468e6652c128\":{\"position\":{\"x\":2567,\"y\":207},\"dynamicMetadata\":{\"hooName\":false},\"useDynamic\":false},\"cd550c28-17a4-412a-b20e-18489c6ccde7\":{\"position\":{\"x\":2655,\"y\":746},\"conditionMetadata\":[{\"id\":\"211c2ed2-4419-4fd2-95da-89d632379065\",\"value\":\"1\"},{\"id\":\"ab9e8d93-e48a-449a-bf73-a26b11198d96\",\"value\":\"2\"}],\"useDynamic\":false,\"useLexBotDropdown\":true,\"useDynamicLexBotArn\":false},\"6c9ad66b-5685-4e5d-b253-3c4e7054704d\":{\"position\":{\"x\":2901,\"y\":717},\"dynamicMetadata\":{\"callBackDate\":true,\"callBackPhoneNumber\":true,\"callBackTime\":true,\"HOONAME\":false},\"useDynamic\":false},\"f868abe6-ffcb-4d0a-b9d4-d50146de9d0c\":{\"position\":{\"x\":2900,\"y\":948},\"useDynamic\":false},\"79ad8c83-9f37-4e2b-8f94-8c8599bd38ee\":{\"position\":{\"x\":3830,\"y\":433}},\"48d70790-0c57-45c5-bfe7-fe8f7544343a\":{\"position\":{\"x\":3154,\"y\":665},\"useDynamic\":false},\"c13401f0-3634-459f-a712-cf36713dd9c9\":{\"position\":{\"x\":3391,\"y\":668},\"dynamicMetadata\":{\"SFNExecutionARN\":true},\"useDynamic\":false},\"f2819365-c3c7-4c6e-9fc0-2e96d6a06bff\":{\"position\":{\"x\":422,\"y\":314},\"conditionMetadata\":[{\"id\":\"96627905-f353-4d75-811d-65b7ac73d2a1\",\"value\":\"FallbackIntent\"},{\"id\":\"fa239ba4-6b90-4459-878d-bbafe9b4879a\",\"value\":\"CallBackDateTime\"}],\"useDynamic\":false,\"dynamicMetadata\":{},\"useLexBotDropdown\":true,\"useDynamicLexBotArn\":false,\"lexV2BotName\":\"CallBackRequestBotV2\",\"lexV2BotAliasName\":\"CBLexBotV2Alias\"},\"bfbb2e6e-5d38-41de-90ef-a0a509b71565\":{\"position\":{\"x\":3610,\"y\":1015},\"useDynamic\":false},\"2eeaa2d6-01e7-4599-8646-54736b1b21c7\":{\"position\":{\"x\":3150,\"y\":944},\"dynamicMetadata\":{\"callBackDate\":true,\"callBackTime\":true,\"CallBackConfirmation\":false,\"HOONAME\":false},\"useDynamic\":false},\"d73e01c1-9154-4437-9b7a-95f192c4979c\":{\"position\":{\"x\":3385,\"y\":1234},\"dynamicMetadata\":{\"SFNExecutionARN\":true},\"useDynamic\":false}}},\"Actions\":[{\"Identifier\":\"db9a362d-aa42-4f99-86ad-4d9e17a5aa43\",\"Type\":\"DisconnectParticipant\",\"Parameters\":{},\"Transitions\":{}},{\"Identifier\":\"84412a25-4f1f-4f8a-800f-72b5827115a0\",\"Parameters\":{\"Text\":\"Slot is available.\"},\"Transitions\":{\"NextAction\":\"cd550c28-17a4-412a-b20e-18489c6ccde7\",\"Errors\":[{\"NextAction\":\"cd550c28-17a4-412a-b20e-18489c6ccde7\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"MessageParticipant\"},{\"Identifier\":\"8bed348e-ecb5-47f2-b0bd-a6c074ba579e\",\"Parameters\":{\"Text\":\"You entered $.Lex.Slots.date date and $.Lex.Slots.time date time\"},\"Transitions\":{\"NextAction\":\"eaa02efa-540a-49d8-bd63-6b538af959eb\",\"Errors\":[],\"Conditions\":[]},\"Type\":\"MessageParticipant\"},{\"Identifier\":\"e8b74e72-86f8-4966-b521-b3a6d86492b4\",\"Parameters\":{\"FlowLoggingBehavior\":\"Enabled\"},\"Transitions\":{\"NextAction\":\"f2819365-c3c7-4c6e-9fc0-2e96d6a06bff\",\"Errors\":[],\"Conditions\":[]},\"Type\":\"UpdateFlowLoggingBehavior\"},{\"Identifier\":\"b14e28e7-b410-4ee2-becc-bc10d4f34f23\",\"Parameters\":{\"SSML\":\"<speak>There are $.Attributes.Available_Slot slots available at <say-as interpret-as=\\\"date\\\" format=\\\"ymd\\\">$.Attributes.callBackDate</say-as> at <say-as interpret-as=\\\"time\\\">$.Attributes.callBackTime</say-as></speak>\"},\"Transitions\":{\"NextAction\":\"cd550c28-17a4-412a-b20e-18489c6ccde7\",\"Errors\":[{\"NextAction\":\"cd550c28-17a4-412a-b20e-18489c6ccde7\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"MessageParticipant\"},{\"Identifier\":\"db50269f-9fce-4fdc-bbee-40f7fa8a8dbb\",\"Parameters\":{\"ComparisonValue\":\"$.External.status\"},\"Transitions\":{\"NextAction\":\"bfbb2e6e-5d38-41de-90ef-a0a509b71565\",\"Errors\":[{\"NextAction\":\"bfbb2e6e-5d38-41de-90ef-a0a509b71565\",\"ErrorType\":\"NoMatchingCondition\"}],\"Conditions\":[{\"NextAction\":\"9e1e0ec1-e3bf-4510-abd7-ebba28e34cef\",\"Condition\":{\"Operator\":\"Equals\",\"Operands\":[\"out_of_hours\"]}},{\"NextAction\":\"47cd3918-e1f6-4635-8f94-30af4596c81f\",\"Condition\":{\"Operator\":\"Equals\",\"Operands\":[\"out_of_allowed_day_in_advanced\"]}},{\"NextAction\":\"d70c3a2d-a2ca-4383-88b3-d3cff11fc72d\",\"Condition\":{\"Operator\":\"Equals\",\"Operands\":[\"past_time_requested\"]}},{\"NextAction\":\"84412a25-4f1f-4f8a-800f-72b5827115a0\",\"Condition\":{\"Operator\":\"Equals\",\"Operands\":[\"slots_available\"]}},{\"NextAction\":\"7db7f1c2-46fc-4aaf-a984-3163024e5356\",\"Condition\":{\"Operator\":\"Equals\",\"Operands\":[\"no_slots_available\"]}}]},\"Type\":\"Compare\"},{\"Identifier\":\"ffabc50b-8843-49bd-bbd4-943977bdeccf\",\"Parameters\":{\"ComparisonValue\":\"$.Attributes.SLOT_AVAILABLE\"},\"Transitions\":{\"NextAction\":\"79ad8c83-9f37-4e2b-8f94-8c8599bd38ee\",\"Errors\":[{\"NextAction\":\"79ad8c83-9f37-4e2b-8f94-8c8599bd38ee\",\"ErrorType\":\"NoMatchingCondition\"}],\"Conditions\":[{\"NextAction\":\"b14e28e7-b410-4ee2-becc-bc10d4f34f23\",\"Condition\":{\"Operator\":\"Equals\",\"Operands\":[\"true\"]}}]},\"Type\":\"Compare\"},{\"Identifier\":\"a932ed28-7977-47b6-99b4-beebd739625b\",\"Parameters\":{\"Attributes\":{\"SFNExecutionARN\":\"$.External.SFNExecutionARN\"}},\"Transitions\":{\"NextAction\":\"db50269f-9fce-4fdc-bbee-40f7fa8a8dbb\",\"Errors\":[{\"NextAction\":\"db50269f-9fce-4fdc-bbee-40f7fa8a8dbb\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"UpdateContactAttributes\"},{\"Identifier\":\"6e306611-08f3-4a65-be63-e69740f237ea\",\"Parameters\":{\"Text\":\"Error in Welcome contact flow\"},\"Transitions\":{\"NextAction\":\"db9a362d-aa42-4f99-86ad-4d9e17a5aa43\",\"Errors\":[{\"NextAction\":\"db9a362d-aa42-4f99-86ad-4d9e17a5aa43\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"MessageParticipant\"},{\"Identifier\":\"eaa02efa-540a-49d8-bd63-6b538af959eb\",\"Parameters\":{\"Attributes\":{\"callBackDate\":\"$.Lex.Slots.date\",\"callBackTime\":\"$.Lex.Slots.time\"}},\"Transitions\":{\"NextAction\":\"1ec9f841-ddba-48a8-96a8-12bf120ffa13\",\"Errors\":[{\"NextAction\":\"1ec9f841-ddba-48a8-96a8-12bf120ffa13\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"UpdateContactAttributes\"},{\"Identifier\":\"1ec9f841-ddba-48a8-96a8-12bf120ffa13\",\"Parameters\":{\"LambdaFunctionARN\":\"CbProcessRequestedDateTime\",\"InvocationTimeLimitSeconds\":\"8\",\"LambdaInvocationAttributes\":{\"callBackDate\":\"$.Attributes.callBackDate\",\"callBackTime\":\"$.Attributes.callBackTime\",\"CallBackConfirmation\":\"true\",\"HOONAME\":\"Basic Hours\"}},\"Transitions\":{\"NextAction\":\"a932ed28-7977-47b6-99b4-beebd739625b\",\"Errors\":[{\"NextAction\":\"6e306611-08f3-4a65-be63-e69740f237ea\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"InvokeLambdaFunction\"},{\"Identifier\":\"50935c43-2a1d-4536-af3c-a16b1ac34fae\",\"Parameters\":{\"Attributes\":{\"callBackDate\":\"$.External.slotDate\",\"SFNExecutionARN\":\"$.External.SFNExecutionARN\",\"callBackTime\":\"$.External.slotTime\",\"SLOT_AVAILABLE\":\"$.External.SLOT_AVAILABLE\",\"Available_Slot\":\"$.External.Available_Slot\"}},\"Transitions\":{\"NextAction\":\"ffabc50b-8843-49bd-bbd4-943977bdeccf\",\"Errors\":[{\"NextAction\":\"ffabc50b-8843-49bd-bbd4-943977bdeccf\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"UpdateContactAttributes\"},{\"Identifier\":\"dc303b42-b3ce-4de8-aff9-4ddd2c72e895\",\"Parameters\":{\"Text\":\"Error in Welcome contact flow\"},\"Transitions\":{\"NextAction\":\"79ad8c83-9f37-4e2b-8f94-8c8599bd38ee\",\"Errors\":[{\"NextAction\":\"79ad8c83-9f37-4e2b-8f94-8c8599bd38ee\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"MessageParticipant\"},{\"Identifier\":\"292cebba-a8ea-4e88-9fbb-a9f5dff768dc\",\"Parameters\":{\"Text\":\"Sorry, the day or time you requested has not been recognized.\"},\"Transitions\":{\"NextAction\":\"02fa6720-0f9d-4490-a409-468e6652c128\",\"Errors\":[{\"NextAction\":\"02fa6720-0f9d-4490-a409-468e6652c128\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"MessageParticipant\"},{\"Identifier\":\"9e1e0ec1-e3bf-4510-abd7-ebba28e34cef\",\"Parameters\":{\"Text\":\"Sorry, out of Hour time request.\"},\"Transitions\":{\"NextAction\":\"02fa6720-0f9d-4490-a409-468e6652c128\",\"Errors\":[{\"NextAction\":\"02fa6720-0f9d-4490-a409-468e6652c128\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"MessageParticipant\"},{\"Identifier\":\"47cd3918-e1f6-4635-8f94-30af4596c81f\",\"Parameters\":{\"Text\":\"Sorry, the day you requested is too far in advanced.\"},\"Transitions\":{\"NextAction\":\"02fa6720-0f9d-4490-a409-468e6652c128\",\"Errors\":[{\"NextAction\":\"02fa6720-0f9d-4490-a409-468e6652c128\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"MessageParticipant\"},{\"Identifier\":\"d70c3a2d-a2ca-4383-88b3-d3cff11fc72d\",\"Parameters\":{\"Text\":\"You requested a past time.\"},\"Transitions\":{\"NextAction\":\"02fa6720-0f9d-4490-a409-468e6652c128\",\"Errors\":[{\"NextAction\":\"02fa6720-0f9d-4490-a409-468e6652c128\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"MessageParticipant\"},{\"Identifier\":\"7db7f1c2-46fc-4aaf-a984-3163024e5356\",\"Parameters\":{\"Text\":\"Sorry, no slots are available at the time.\"},\"Transitions\":{\"NextAction\":\"02fa6720-0f9d-4490-a409-468e6652c128\",\"Errors\":[{\"NextAction\":\"02fa6720-0f9d-4490-a409-468e6652c128\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"MessageParticipant\"},{\"Identifier\":\"02fa6720-0f9d-4490-a409-468e6652c128\",\"Parameters\":{\"LambdaFunctionARN\":\"CbGetFirstAvailableSlot\",\"InvocationTimeLimitSeconds\":\"8\",\"LambdaInvocationAttributes\":{\"hooName\":\"Basic Hours\"}},\"Transitions\":{\"NextAction\":\"50935c43-2a1d-4536-af3c-a16b1ac34fae\",\"Errors\":[{\"NextAction\":\"dc303b42-b3ce-4de8-aff9-4ddd2c72e895\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"InvokeLambdaFunction\"},{\"Identifier\":\"cd550c28-17a4-412a-b20e-18489c6ccde7\",\"Parameters\":{\"Text\":\"To confirm press1. Press2 to retry.\",\"StoreInput\":\"False\",\"InputTimeLimitSeconds\":\"5\"},\"Transitions\":{\"NextAction\":\"f868abe6-ffcb-4d0a-b9d4-d50146de9d0c\",\"Errors\":[{\"NextAction\":\"f868abe6-ffcb-4d0a-b9d4-d50146de9d0c\",\"ErrorType\":\"NoMatchingError\"},{\"NextAction\":\"f868abe6-ffcb-4d0a-b9d4-d50146de9d0c\",\"ErrorType\":\"NoMatchingCondition\"},{\"NextAction\":\"f868abe6-ffcb-4d0a-b9d4-d50146de9d0c\",\"ErrorType\":\"InputTimeLimitExceeded\"}],\"Conditions\":[{\"NextAction\":\"6c9ad66b-5685-4e5d-b253-3c4e7054704d\",\"Condition\":{\"Operator\":\"Equals\",\"Operands\":[\"1\"]}},{\"NextAction\":\"f868abe6-ffcb-4d0a-b9d4-d50146de9d0c\",\"Condition\":{\"Operator\":\"Equals\",\"Operands\":[\"2\"]}}]},\"Type\":\"GetParticipantInput\"},{\"Identifier\":\"6c9ad66b-5685-4e5d-b253-3c4e7054704d\",\"Parameters\":{\"LambdaFunctionARN\":\"CbPlaceCallbackRequest\",\"InvocationTimeLimitSeconds\":\"8\",\"LambdaInvocationAttributes\":{\"callBackDate\":\"$.Attributes.callBackDate\",\"callBackPhoneNumber\":\"$.CustomerEndpoint.Address\",\"callBackTime\":\"$.Attributes.callBackTime\",\"HOONAME\":\"Basic Hours\"}},\"Transitions\":{\"NextAction\":\"48d70790-0c57-45c5-bfe7-fe8f7544343a\",\"Errors\":[{\"NextAction\":\"bfbb2e6e-5d38-41de-90ef-a0a509b71565\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"InvokeLambdaFunction\"},{\"Identifier\":\"f868abe6-ffcb-4d0a-b9d4-d50146de9d0c\",\"Parameters\":{\"Text\":\"Your callback is not scheduled. Thank you.\"},\"Transitions\":{\"NextAction\":\"2eeaa2d6-01e7-4599-8646-54736b1b21c7\",\"Errors\":[],\"Conditions\":[]},\"Type\":\"MessageParticipant\"},{\"Identifier\":\"79ad8c83-9f37-4e2b-8f94-8c8599bd38ee\",\"Type\":\"DisconnectParticipant\",\"Parameters\":{},\"Transitions\":{}},{\"Identifier\":\"48d70790-0c57-45c5-bfe7-fe8f7544343a\",\"Parameters\":{\"Text\":\"Your callback is successfully scheduled and will be placed in a 15 min time window\"},\"Transitions\":{\"NextAction\":\"c13401f0-3634-459f-a712-cf36713dd9c9\",\"Errors\":[{\"NextAction\":\"c13401f0-3634-459f-a712-cf36713dd9c9\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"MessageParticipant\"},{\"Identifier\":\"c13401f0-3634-459f-a712-cf36713dd9c9\",\"Parameters\":{\"LambdaFunctionARN\":\"CbAbortSfn\",\"InvocationTimeLimitSeconds\":\"8\",\"LambdaInvocationAttributes\":{\"SFNExecutionARN\":\"$.Attributes.SFNExecutionARN\"}},\"Transitions\":{\"NextAction\":\"79ad8c83-9f37-4e2b-8f94-8c8599bd38ee\",\"Errors\":[{\"NextAction\":\"79ad8c83-9f37-4e2b-8f94-8c8599bd38ee\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"InvokeLambdaFunction\"},{\"Identifier\":\"f2819365-c3c7-4c6e-9fc0-2e96d6a06bff\",\"Parameters\":{\"Text\":\"Please enter date and time for a callback.\",\"LexV2Bot\":{\"AliasArn\":\"arn:aws:lex:us-east-1:999999999999:bot-alias/VQSA4PJHHA/ISALCLDL6Z\"}},\"Transitions\":{\"NextAction\":\"6e306611-08f3-4a65-be63-e69740f237ea\",\"Errors\":[{\"NextAction\":\"6e306611-08f3-4a65-be63-e69740f237ea\",\"ErrorType\":\"NoMatchingError\"},{\"NextAction\":\"6e306611-08f3-4a65-be63-e69740f237ea\",\"ErrorType\":\"NoMatchingCondition\"}],\"Conditions\":[{\"NextAction\":\"292cebba-a8ea-4e88-9fbb-a9f5dff768dc\",\"Condition\":{\"Operator\":\"Equals\",\"Operands\":[\"FallbackIntent\"]}},{\"NextAction\":\"8bed348e-ecb5-47f2-b0bd-a6c074ba579e\",\"Condition\":{\"Operator\":\"Equals\",\"Operands\":[\"CallBackDateTime\"]}}]},\"Type\":\"ConnectParticipantWithLexBot\"},{\"Identifier\":\"bfbb2e6e-5d38-41de-90ef-a0a509b71565\",\"Parameters\":{\"Text\":\"Error in Welcome contact flow\"},\"Transitions\":{\"NextAction\":\"79ad8c83-9f37-4e2b-8f94-8c8599bd38ee\",\"Errors\":[{\"NextAction\":\"79ad8c83-9f37-4e2b-8f94-8c8599bd38ee\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"MessageParticipant\"},{\"Identifier\":\"2eeaa2d6-01e7-4599-8646-54736b1b21c7\",\"Parameters\":{\"LambdaFunctionARN\":\"CbProcessRequestedDateTime\",\"InvocationTimeLimitSeconds\":\"8\",\"LambdaInvocationAttributes\":{\"callBackDate\":\"$.Attributes.callBackDate\",\"callBackTime\":\"$.Attributes.callBackTime\",\"CallBackConfirmation\":\"false\",\"HOONAME\":\"Basic Hours\"}},\"Transitions\":{\"NextAction\":\"d73e01c1-9154-4437-9b7a-95f192c4979c\",\"Errors\":[{\"NextAction\":\"bfbb2e6e-5d38-41de-90ef-a0a509b71565\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"InvokeLambdaFunction\"},{\"Identifier\":\"d73e01c1-9154-4437-9b7a-95f192c4979c\",\"Parameters\":{\"LambdaFunctionARN\":\"CbAbortSfn\",\"InvocationTimeLimitSeconds\":\"8\",\"LambdaInvocationAttributes\":{\"SFNExecutionARN\":\"$.Attributes.SFNExecutionARN\"}},\"Transitions\":{\"NextAction\":\"f2819365-c3c7-4c6e-9fc0-2e96d6a06bff\",\"Errors\":[{\"NextAction\":\"bfbb2e6e-5d38-41de-90ef-a0a509b71565\",\"ErrorType\":\"NoMatchingError\"}],\"Conditions\":[]},\"Type\":\"InvokeLambdaFunction\"}]}"
      Type: CONTACT_FLOW
  CbHoursOfOperationDetailsTable:
    Type: 'AWS::DynamoDB::Table'
    Properties:
      AttributeDefinitions:
        - AttributeName: HoursOfOperationName
          AttributeType: S
        - AttributeName: WeekDay
          AttributeType: S
      KeySchema:
        - AttributeName: HoursOfOperationName
          KeyType: HASH
        - AttributeName: WeekDay
          KeyType: RANGE
      BillingMode: PAY_PER_REQUEST
    Metadata:
      'AWS::CloudFormation::Designer':
        id: 0015b0bf-9a2f-48a3-b51a-f2b57bf2bd09
  CbSlotAvailabilityTable:
    Type: 'AWS::DynamoDB::Table'
    Properties:
      AttributeDefinitions:
        - AttributeName: SlotDateTime
          AttributeType: S
        - AttributeName: HoursOfOperationName
          AttributeType: S
      KeySchema:
        - AttributeName: SlotDateTime
          KeyType: HASH
        - AttributeName: HoursOfOperationName
          KeyType: RANGE
      BillingMode: PAY_PER_REQUEST
    Metadata:
      'AWS::CloudFormation::Designer':
        id: 4ef1c0e9-9d95-477e-b877-f110a6b720f8
  CbStepFunctionTable:
    Type: 'AWS::DynamoDB::Table'
    Properties:
      AttributeDefinitions:
        - AttributeName: ContactId
          AttributeType: S
      KeySchema:
        - AttributeName: ContactId
          KeyType: HASH
      BillingMode: PAY_PER_REQUEST
      TimeToLiveSpecification:
        AttributeName: TTL
        Enabled: True      
    Metadata:
      'AWS::CloudFormation::Designer':
        id: 95a0538f-aa6c-4503-858d-f429d64032dc  
  PytzModLayer:
    Type: "AWS::Lambda::LayerVersion"
    Properties:
      CompatibleRuntimes:
      - python3.9
      Content:
        S3Bucket: !Ref callbackblogartifacts
        S3Key: !Join 
            - ''
            - - !FindInMap 
                - FunctionMap
                - Configuration
                - S3KeyLambdalayer
              - pytz2022mod.zip
      LayerName: "PytzModLayer"
    DependsOn:
      - CopyCfnStacksLambdaTrigger  
  CbAbortSfn:
    Type: 'AWS::Lambda::Function'
    Properties:
      Description: AWS Lambda Function to abort the step function
      Handler: lambda_function.lambda_handler
      Role: !GetAtt CbAbortSfnLambdaExecutionRole.Arn
      Runtime: python3.9
      MemorySize: 128
      Timeout: 30
      Code:
        S3Bucket: !Ref callbackblogartifacts
        S3Key: !Join 
          - ''
          - - !FindInMap 
              - FunctionMap
              - Configuration
              - S3KeyLambda
            - cb-abort-sfn.zip
    DependsOn:
      - CopyCfnStacksLambdaTrigger
    Metadata:
      'AWS::CloudFormation::Designer':
        id: 995b9c18-5532-4d26-862b-614ac501f187
  CbAbortSfnLambdaExecutionRole:
    Type: AWS::IAM::Role    
    Properties:
      Description: IAM Role for the CbAbortSfn
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
        - 'arn:aws:iam::aws:policy/AWSStepFunctionsFullAccess'
    Metadata:
      'AWS::CloudFormation::Designer':
        id: c3bf5e85-496c-4436-abf4-e14aa94b4464
  CbAddAdditionalDayAvailabilitySlots:
    Type: 'AWS::Lambda::Function'
    Properties:
      Description: AWS Lambda Function to add additional day's worth of availability slots
      Handler: lambda_function.lambda_handler
      Layers:
        - !Ref PytzModLayer
      Role: !GetAtt CbAddAdditionalDayAvailabilitySlotsLambdaExecutionRole.Arn
      Runtime: python3.9
      MemorySize: 128
      Timeout: 500
      Environment:
        Variables:
          INSTANCE_ID: !Ref instanceId
          REGION: !Ref 'AWS::Region'
          SLOT_AVAILABILITY_TABLE_NAME: !Ref CbSlotAvailabilityTable
          HOO_DETAILS_TABLE_NAME: !Ref CbHoursOfOperationDetailsTable
          LOG_LEVEL: !Ref LogLevel
          HOURLY_SLOTS: 10
      Code:
        S3Bucket: !Ref callbackblogartifacts
        S3Key: !Join 
          - ''
          - - !FindInMap 
              - FunctionMap
              - Configuration
              - S3KeyLambda
            - cb-add-additional-day-availability-slots.zip
    DependsOn:
      - CopyCfnStacksLambdaTrigger
  CbAddAdditionalDayAvailabilitySlotsLambdaExecutionRole:
    Type: 'AWS::IAM::Role'    
    Properties:
      Description: IAM Role for the CbAddAdditionalDayAvailabilitySlotsLambdaExecutionRole
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
        - 'arn:aws:iam::aws:policy/AmazonConnect_FullAccess'
        - 'arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess'
  CbGetHooFromConnectApi:
    Type: 'AWS::Lambda::Function'
    Properties:
      Description: AWS Lambda Function to get the Hours of Operation from Connect instance
      Handler: lambda_function.lambda_handler
      Role: !GetAtt CbGetHooFromConnectApiLambdaExecutionRole.Arn
      Runtime: python3.9
      MemorySize: 128
      Timeout: 180
      Environment:
        Variables:
          INSTANCE_ID: !Ref instanceId
          REGION: !Ref 'AWS::Region'
          HOO_DETAILS_TABLE_NAME: !Ref CbHoursOfOperationDetailsTable
          LOG_LEVEL: !Ref LogLevel
      Code:
        S3Bucket: !Ref callbackblogartifacts
        S3Key: !Join 
          - ''
          - - !FindInMap 
              - FunctionMap
              - Configuration
              - S3KeyLambda
            - cb-get-hoo-from-connect-api.zip
    DependsOn: 
      - CopyCfnStacksLambdaTrigger
  CbGetHooFromConnectApiLambdaExecutionRole:
    Type: 'AWS::IAM::Role'    
    Properties:
      Description: IAM Role for the CbGetHooFromConnectApi lambda
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
        - 'arn:aws:iam::aws:policy/AmazonConnect_FullAccess'
        - 'arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess'
    Metadata:
      'AWS::CloudFormation::Designer':
        id: 63e4060c-46a5-4cbf-ac24-f954b1916e0c
  CbCreateAvailabilitySlotData:
    Type: 'AWS::Lambda::Function'
    Properties:
      Description: AWS Lambda Function to create the availability slot data
      Handler: lambda_function.lambda_handler
      Layers:
      - !Ref PytzModLayer
      Role: !GetAtt CbCreateAvailabilitySlotDataLambdaExecutionRole.Arn
      Runtime: python3.9
      MemorySize: 128
      Timeout: 500
      Environment:
        Variables:
          INSTANCE_ID: !Ref instanceId
          REGION: !Ref 'AWS::Region'
          SLOT_AVAILABILITY_TABLE_NAME: !Ref CbSlotAvailabilityTable
          HOO_DETAILS_TABLE_NAME: !Ref CbHoursOfOperationDetailsTable
          LOG_LEVEL: !Ref LogLevel
          DAYS_IN_ADVANCE: 7
          HOURLY_SLOTS: 10
      Code:
        S3Bucket: !Ref callbackblogartifacts
        S3Key: !Join 
          - ''
          - - !FindInMap 
              - FunctionMap
              - Configuration
              - S3KeyLambda
            - cb-create-availability-slot-data.zip
    DependsOn: 
      - CopyCfnStacksLambdaTrigger
  CbCreateAvailabilitySlotDataLambdaExecutionRole:
    Type: 'AWS::IAM::Role'    
    Properties:
      Description: IAM Role for the CbCreateAvailabilitySlotDataLambdaExecutionRole
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
        - 'arn:aws:iam::aws:policy/AmazonConnect_FullAccess'
        - 'arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess'
    Metadata:
      'AWS::CloudFormation::Designer':
        id: b735031d-13dd-4933-947a-91a3908a99b9
  CbGetFirstAvailableSlot:
    Type: 'AWS::Lambda::Function'
    Properties:
      Description: AWS Lambda Function to get the first available slot
      Handler: lambda_function.lambda_handler
      Layers:
      - !Ref PytzModLayer
      Role: !GetAtt CbGetFirstAvailableSlotLambdaExecutionRole.Arn
      Runtime: python3.9
      MemorySize: 128
      Timeout: 30
      Environment:
        Variables:
          REGION: !Ref 'AWS::Region'
          SLOT_DATETIME_UPDATE_SFN_ARN: !Ref CbSlotDateTimeUpdateSfn
          HOO_DETAILS_TABLE_NAME: !Ref CbHoursOfOperationDetailsTable
          SLOT_AVAILABILITY_TABLE_NAME: !Ref CbSlotAvailabilityTable
          LOG_LEVEL: !Ref LogLevel
          DAYS_IN_ADVANCE: 7
      Code:
        S3Bucket: !Ref  callbackblogartifacts
        S3Key: !Join 
          - ''
          - - !FindInMap 
              - FunctionMap
              - Configuration
              - S3KeyLambda
            - cb-get-first-available-slot.zip
    DependsOn:
      - CopyCfnStacksLambdaTrigger
  CbGetFirstAvailableSlotLambdaExecutionRole:
    Type: 'AWS::IAM::Role'
    Properties:
      Description: IAM Role for the CbGetFirstAvailableSlot lambda
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
        - 'arn:aws:iam::aws:policy/AWSStepFunctionsFullAccess'
        - 'arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess'
    Metadata:
      'AWS::CloudFormation::Designer':
        id: cd3c8c55-cd46-4341-85a9-39c6f269d07a
  CbIncrementAvailabilitySlot:
    Type: 'AWS::Lambda::Function'
    Properties:
      Description: AWS Lambda Function to increment availability slot
      Handler: lambda_function.lambda_handler
      Role: !GetAtt CbIncrementAvailabilitySlotLambdaExecutionRole.Arn
      Runtime: python3.9
      MemorySize: 128
      Timeout: 30
      Environment:
        Variables:
          REGION: !Ref 'AWS::Region'
          SLOT_AVAILABILITY_TABLE_NAME: !Ref CbSlotAvailabilityTable
          LOG_LEVEL: !Ref LogLevel
      Code:
        S3Bucket: !Ref callbackblogartifacts
        S3Key: !Join 
          - ''
          - - !FindInMap 
              - FunctionMap
              - Configuration
              - S3KeyLambda
            - cb-increment-availability-slot.zip
    DependsOn:
      - CopyCfnStacksLambdaTrigger
  CbIncrementAvailabilitySlotLambdaExecutionRole:
    Type: 'AWS::IAM::Role'    
    Properties:
      Description: IAM Role for the CbIncrementAvailabilitySlot lambda
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
        - 'arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess'
    Metadata:
      'AWS::CloudFormation::Designer':
        id: bd6325ff-4152-494d-8f08-ce051e5b2696
  CbPlaceCallbackRequest:
    Type: 'AWS::Lambda::Function'
    Properties:
      Description: AWS Lambda Function to place a callback request
      Handler: lambda_function.lambda_handler
      Layers:
      - !Ref PytzModLayer
      Role: !GetAtt CbPlaceCallbackRequestLambdaExecutionRole.Arn
      Runtime: python3.9
      MemorySize: 128
      Timeout: 30
      Environment:
        Variables:
          REGION: !Ref 'AWS::Region'
          PLACE_OUTBOUND_CALL_SFN_ARN: !Ref CbPlaceOutboundCallSfn
          CALLBACK_SFN_TABLE_NAME: !Ref CbStepFunctionTable
          HOO_DETAILS_TABLE_NAME: !Ref CbHoursOfOperationDetailsTable
          PLACE_OUTBOUND_CALL_LAMBDA_ARN: !Ref CbPlaceOutboundCall
          LOG_LEVEL: !Ref LogLevel
          TTL_DAYS: 30
      Code:
        S3Bucket: !Ref callbackblogartifacts
        S3Key: !Join 
          - ''
          - - !FindInMap 
              - FunctionMap
              - Configuration
              - S3KeyLambda
            - cb-place-callback-request.zip
    DependsOn:
      - CopyCfnStacksLambdaTrigger
  CbPlaceCallbackRequestLambdaExecutionRole:
    Type: 'AWS::IAM::Role'    
    Properties:
      Description: IAM Role for the CbPlaceCallbackRequest lambda
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
        - 'arn:aws:iam::aws:policy/AWSStepFunctionsFullAccess'
        - 'arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess'
    Metadata:
      'AWS::CloudFormation::Designer':
        id: 17d04bb3-7199-40da-85c0-b1a8abb6c321
  CbPlaceOutboundCall:
    Type: 'AWS::Lambda::Function'
    Properties:
      Description: AWS Lambda Function to place an outbound call
      Handler: lambda_function.lambda_handler
      Role: !GetAtt CbPlaceOutboundCallLambdaExecutionRole.Arn
      Runtime: python3.9
      MemorySize: 128
      Timeout: 30
      Environment:
        Variables:
          REGION: !Ref 'AWS::Region'
          INSTANCE_ID: !Ref instanceId
          CONTACT_FLOW_ID: !Select [1, !Split ["contact-flow/", !Ref ACBlogCallbackPlacingFlow]]
          HELPER_PHONE_NUMBER: !Ref helperPhoneNumber
          CALLBACK_SFN_TABLE_NAME: !Ref CbStepFunctionTable
          LOG_LEVEL: !Ref LogLevel
      Code:
        S3Bucket: !Ref callbackblogartifacts
        S3Key: !Join 
          - ''
          - - !FindInMap 
              - FunctionMap
              - Configuration
              - S3KeyLambda
            - cb-place-outbound-call.zip
    DependsOn:
      - CopyCfnStacksLambdaTrigger
  CbPlaceOutboundCallLambdaExecutionRole:
    Type: 'AWS::IAM::Role'    
    Properties:
      Description: IAM Role for the CbPlaceOutboundCall lambda
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
        - 'arn:aws:iam::aws:policy/AmazonConnect_FullAccess'
        - 'arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess'
    Metadata:
      'AWS::CloudFormation::Designer':
        id: 3c04dec0-64cb-4979-8753-2a05b4408ccb
  CbProcessRequestedDateTime:
    Type: 'AWS::Lambda::Function'
    Properties:
      Description: AWS Lambda Function to process requested data time
      Handler: lambda_function.lambda_handler
      Layers:
      - !Ref PytzModLayer
      Role: !GetAtt CbProcessRequestedDateTimeLambdaExecutionRole.Arn
      Runtime: python3.9
      MemorySize: 128
      Timeout: 30
      Environment:
        Variables:
          REGION: !Ref 'AWS::Region'
          SLOT_DATETIME_UPDATE_SFN_ARN: !Ref CbSlotDateTimeUpdateSfn
          SLOT_AVAILABILITY_TABLE_NAME: !Ref CbSlotAvailabilityTable
          HOO_DETAILS_TABLE_NAME: !Ref CbHoursOfOperationDetailsTable
          LOG_LEVEL: !Ref LogLevel
          DAYS_IN_ADVANCE: 7
      Code:
        S3Bucket: !Ref callbackblogartifacts
        S3Key: !Join 
          - ''
          - - !FindInMap 
              - FunctionMap
              - Configuration
              - S3KeyLambda
            - cb-process-requested-date-time.zip
    DependsOn:
      - CopyCfnStacksLambdaTrigger
  CbProcessRequestedDateTimeLambdaExecutionRole:
    Type: 'AWS::IAM::Role'    
    Properties:
      Description: IAM Role for the CbProcessRequestedDateTime lambda
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
        - 'arn:aws:iam::aws:policy/AWSStepFunctionsFullAccess'
        - 'arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess'
    Metadata:
      'AWS::CloudFormation::Designer':
        id: ae1bc4b7-8420-4b62-8710-3b60534ecd0c
  CbSlotDateTimeUpdateSfn:
    Type: 'AWS::StepFunctions::StateMachine'
    Properties:
      DefinitionString: !Sub 
        - |-
          {
            "Comment": "A step function to update/increment the availability slot",
            "StartAt": "WaitState",
            "States": {
              "WaitState": {
                "Type": "Wait",
                "Seconds": 60,
                "Next": "InvokeLambdafunction"
              },
              "InvokeLambdafunction": {
                "Type": "Task",
                "Resource": "${lambdaArn}",
                "End": true
              }
            }
          }
        - lambdaArn: !GetAtt CbIncrementAvailabilitySlot.Arn
      RoleArn: !GetAtt CbSlotDateTimeUpdateSfnRole.Arn
      StateMachineName: CbSlotDateTimeUpdateSfn
    Metadata:
      'AWS::CloudFormation::Designer':
        id: e2f7cfad-ef7a-4da4-aefe-f8a11b9bcb39
  CbSlotDateTimeUpdateSfnRole:
    Type: 'AWS::IAM::Role'    
    Properties:
      Description: IAM Role for the CbSlotDateTimeUpdateSfn Step Function
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - states.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/AWSLambda_FullAccess'
        - 'arn:aws:iam::aws:policy/CloudWatchFullAccess'
    Metadata:
      'AWS::CloudFormation::Designer':
        id: c9f2dbc6-03b8-4119-917b-0338175d5a58
  CbPlaceOutboundCallSfn:
    Type: 'AWS::StepFunctions::StateMachine'
    Properties:
      DefinitionString: !Sub 
        - |-
          {
            "Comment": "A step function to place an outbound call after the specified wait time",
            "StartAt": "WaitState",
            "States": {
              "WaitState": {
                "Type": "Wait",
                "TimestampPath": "$.expirydate",
                "Next": "PlaceCallState"
              },
              "PlaceCallState": {
                "Type": "Task",
                "Resource": "arn:aws:states:::lambda:invoke",
                "Parameters": {
                  "FunctionName.$": "$.placeOutboundCallLambdaArn",
                  "Payload.$": "$"
                },
                "End": true
              }
            }
          }
        - lambdaArn: !GetAtt CbIncrementAvailabilitySlot.Arn
      RoleArn: !GetAtt CbPlaceOutboundCallSfnRole.Arn
      StateMachineName: CbPlaceOutboundCallSfn
    Metadata:
      'AWS::CloudFormation::Designer':
        id: 67f963d6-a37e-4bba-8758-59f2118507f9
  CbPlaceOutboundCallSfnRole:
    Type: 'AWS::IAM::Role'    
    Properties:
      Description: IAM Role for the CbPlaceOutboundCallSfn Step Function
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - states.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/AWSLambda_FullAccess'
    Metadata:
      'AWS::CloudFormation::Designer':
        id: e187ec3a-21c2-4d33-97fc-4432b6e3a042
  CbAddLambdasToConnect:
    Type: 'AWS::Lambda::Function'
    Properties:
      Description: AWS Lambda Functions to Connect Instance for use in Contact Flows
      Handler: lambda_function.lambda_handler
      Role: !GetAtt CbAddLambdasToConnectLambdaExecutionRole.Arn
      Runtime: python3.9
      MemorySize: 128
      Timeout: 30
      Environment:
        Variables:
          ACCOUNT_ID: !Ref 'AWS::AccountId'
          REGION: !Ref 'AWS::Region'
          INSTANCE_ID: !Ref instanceId
      Code:
        S3Bucket: !Ref callbackblogartifacts
        S3Key: !Join 
          - ''
          - - !FindInMap 
              - FunctionMap
              - Configuration
              - S3KeyLambda
            - cb-add-lambdas-to-connect.zip
    DependsOn:
      - CopyCfnStacksLambdaTrigger
  CbAddLambdasToConnectLambdaExecutionRole:
    Type: 'AWS::IAM::Role'    
    Properties:
      Description: IAM Role for the CbAddLambdasToConnect lambda
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
        - 'arn:aws:iam::aws:policy/AWSLambda_FullAccess'
        - 'arn:aws:iam::aws:policy/AmazonConnect_FullAccess'
    Metadata:
      'AWS::CloudFormation::Designer':
        id: 8155fb3c-f69e-4d19-8d22-83a207f9fab8
  CbAddLambdasToConnectCustomResource:
    Type: 'Custom::LoadLambda'
    Properties:
      ServiceToken: !GetAtt CbAddLambdasToConnect.Arn
      FunctionArns:
        - !GetAtt CbAbortSfn.Arn
        - !GetAtt CbGetFirstAvailableSlot.Arn
        - !GetAtt CbPlaceCallbackRequest.Arn
        - !GetAtt CbProcessRequestedDateTime.Arn
    Metadata:
      'AWS::CloudFormation::Designer':
        id: d44e88d6-bffc-4b1f-abf6-1c9fd358b8b0  
  CbLexRuntimeRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal: 
              Service:
                - lexv2.amazonaws.com
            Action:
              - "sts:AssumeRole"
      Path: "/"
      Policies:
        - PolicyName: LexRuntimeRolePolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - "polly:SynthesizeSpeech"
                Resource: "*"
  CbLexTemplateBot:
    Type: AWS::Lex::Bot
    Properties:
      Description: Lex bot for collecting date and time of callback
      BotFileS3Location: 
        S3Bucket: !Ref callbackblogartifacts
        S3ObjectKey: !Join
          - ''
          - - !FindInMap
              - FunctionMap
              - Configuration
              - S3KeyLex
            -  CallBackRequestLexV2.zip
      DataPrivacy:
        ChildDirected: false
      IdleSessionTTLInSeconds: 300
      Name: "CallBackRequestBotV2"
      RoleArn: !GetAtt CbLexRuntimeRole.Arn
      AutoBuildBotLocales: true
    DependsOn:
      - CbLexRuntimeRole
      - CopyCfnStacksLambdaTrigger
  CbLexBotVersion:
    Type: AWS::Lex::BotVersion
    Properties:
      BotId: !Ref CbLexTemplateBot
      BotVersionLocaleSpecification:
        - LocaleId: en_US
          BotVersionLocaleDetails:
            SourceBotVersion: DRAFT
    DependsOn:
      - CbLexTemplateBot  
  CbLexBotAlias:
    Type: AWS::Lex::BotAlias
    Properties:
      BotId: !Ref CbLexTemplateBot
      BotAliasName: "CBLexBotV2Alias"
      BotVersion: !GetAtt CbLexBotVersion.BotVersion
      BotAliasLocaleSettings:
        - LocaleId: en_US
          BotAliasLocaleSetting:
            Enabled: true
      SentimentAnalysisSettings:
        DetectSentiment: false
    DependsOn:
      - CbLexBotVersion  
  CbAddLexToConnect:
    Type: 'AWS::Lambda::Function'
    Properties:
      Description: AWS Lambda Functions to add Lex to Connect instance
      Handler: lambda_function.lambda_handler
      Role: !GetAtt CbAddLexToConnectLambdaExecutionRole.Arn
      Runtime: python3.9
      MemorySize: 128
      Timeout: 30
      Environment:
        Variables:
          ACCOUNT_ID: !Ref 'AWS::AccountId'
          REGION: !Ref 'AWS::Region'
          INSTANCE_ID: !Ref instanceId
          BOT_ID: !GetAtt CbLexBotAlias.Arn
      Code:
        S3Bucket: !Ref callbackblogartifacts
        S3Key: !Join 
          - ''
          - - !FindInMap 
              - FunctionMap
              - Configuration
              - S3KeyLambda
            - cb-associate-lex-bot.zip
    DependsOn:
      - CopyCfnStacksLambdaTrigger
  CbAddLexToConnectLambdaExecutionRole:
    Type: 'AWS::IAM::Role'    
    Properties:
      Description: IAM Role for the CbAddLexToConnect lambda
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
        - 'arn:aws:iam::aws:policy/AWSLambda_FullAccess'
        - 'arn:aws:iam::aws:policy/AmazonConnect_FullAccess'
        - 'arn:aws:iam::aws:policy/AmazonLexFullAccess'
  CbAddLexToConnectCustomResource:
    Type: 'Custom::LoadLambda'
    Properties:
      ServiceToken: !GetAtt CbAddLexToConnect.Arn
Outputs:
  S3BucketName:
    Description: The name of the S3 bucket the solution resources are provided
    Value: !Ref callbackblogartifacts
  CbAbortSfnLambdaExecutionRole:
    Description: >-
      The ARN of the IAM role used by the Lambda function to abort the step
      function
    Value: !GetAtt CbAbortSfnLambdaExecutionRole.Arn
  CbCreateAvailabilitySlotDataLambdaExecutionRole:
    Description: >-
      The ARN of the IAM role used by the Lambda function to create availability
      slot data
    Value: !GetAtt CbCreateAvailabilitySlotDataLambdaExecutionRole.Arn
  CbGetFirstAvailableSlotLambdaExecutionRole:
    Description: >-
      The ARN of the IAM role used by the Lambda function to get the first
      available slot
    Value: !GetAtt CbGetFirstAvailableSlotLambdaExecutionRole.Arn
  CbGetHooFromConnectApiLambdaExecutionRole:
    Description: >-
      The ARN of the IAM role used by the Lambda function to get the Hours of
      Operation from Connect instance
    Value: !GetAtt CbGetHooFromConnectApiLambdaExecutionRole.Arn
  CbIncrementAvailabilitySlotLambdaExecutionRole:
    Description: >-
      The ARN of the IAM role used by the Lambda function to increment
      availability slot
    Value: !GetAtt CbIncrementAvailabilitySlotLambdaExecutionRole.Arn
  CbPlaceCallbackRequestLambdaExecutionRole:
    Description: >-
      The ARN of the IAM role used by the Lambda function to place a callback
      request
    Value: !GetAtt CbPlaceCallbackRequestLambdaExecutionRole.Arn
  CbPlaceOutboundCallLambdaExecutionRole:
    Description: >-
      The ARN of the IAM role used by the Lambda function to place an outbound
      call
    Value: !GetAtt CbPlaceOutboundCallLambdaExecutionRole.Arn
  CbProcessRequestedDateTimeLambdaExecutionRole:
    Description: >-
      The ARN of the IAM role used by the Lambda function to process requested
      date time
    Value: !GetAtt CbProcessRequestedDateTimeLambdaExecutionRole.Arn
  CbSlotDateTimeUpdateSfnRole:
    Description: The ARN of the IAM role used by the Step Function CbSlotDateTimeUpdateSfn
    Value: !GetAtt CbSlotDateTimeUpdateSfnRole.Arn
  CbIncrementAvailabilitySlot:
    Description: The ARN of the lambda CbIncrementAvailabilitySlot
    Value: !GetAtt CbIncrementAvailabilitySlot.Arn
  CbPlaceOutboundCallSfnRole:
    Description: The ARN of the IAM role used by the Step Function CbPlaceOutboundCallSfn
    Value: !GetAtt CbPlaceOutboundCallSfnRole.Arn
  CbAddLambdasToConnectLambdaExecutionRole:
    Description: >-
      The ARN of the IAM role used by the Lambda function to add Lambdas to
      Connect
    Value: !GetAtt CbAddLambdasToConnectLambdaExecutionRole.Arn
  CbAddLambdasToConnect:
    Description: The ARN of the Lambda function to add Lambdas to Connect
    Value: !GetAtt CbAddLambdasToConnect.Arn
  ACBlogCallbackPlacingFlowId:
    Description: The Id of the Amazon Connect AC-Blog-Callback-Placing contact flow
    Value: !Select [1, !Split ["contact-flow/", !Ref ACBlogCallbackPlacingFlow]]