{
  "apiVersion": 63,
  "status": "Active",
  "label": "Standard Create Quote from Opportunity",
  "description": "Creates a Quote from an Opportunity and copies source OpportunityLineItem rows into QuoteLineItem rows. Uses a matching Quote RecordType when one exists and otherwise leaves RecordTypeId unset (Master). Runs atomically so child-copy failures roll back the parent Quote.",
  "runAtomically": true,
  "start": {
    "locationX": 40,
    "locationY": 0,
    "connector": {
      "targetReference": "GetOpportunity"
    }
  },
  "variables": [
    {
      "name": "opportunityId",
      "dataType": "String",
      "isInput": true,
      "isOutput": true
    },
    {
      "name": "quoteId",
      "dataType": "String",
      "isOutput": true
    }
  ],
  "recordLookups": [
    {
      "name": "GetOpportunity",
      "label": "Get source Opportunity",
      "locationX": 40,
      "locationY": 120,
      "object": "Opportunity",
      "filters": [
        {
          "field": "Id",
          "operator": "EqualTo",
          "value": {
            "elementReference": "opportunityId"
          }
        }
      ],
      "outputReference": "$opportunity",
      "getFirstRecordOnly": true,
      "connector": {
        "targetReference": "ValidateOpportunityExists"
      }
    },
    {
      "name": "GetSourceOpportunityRecordType",
      "label": "Get source Opportunity RecordType",
      "locationX": 40,
      "locationY": 360,
      "object": "_System_RecordType",
      "filters": [
        {
          "field": "Id",
          "operator": "EqualTo",
          "value": {
            "elementReference": "$opportunity.RecordTypeId"
          }
        }
      ],
      "outputReference": "$sourceOpportunityRecordType",
      "getFirstRecordOnly": true,
      "connector": {
        "targetReference": "GetQuoteObjectMetadata"
      }
    },
    {
      "name": "GetQuoteObjectMetadata",
      "label": "Get Quote object metadata row",
      "locationX": 40,
      "locationY": 480,
      "object": "_System_Object",
      "filters": [
        {
          "field": "ApiName",
          "operator": "EqualTo",
          "value": {
            "stringValue": "Quote"
          }
        }
      ],
      "outputReference": "$quoteObjectMetadata",
      "getFirstRecordOnly": true,
      "connector": {
        "targetReference": "GetMatchingQuoteRecordType"
      }
    },
    {
      "name": "GetMatchingQuoteRecordType",
      "label": "Get matching Quote RecordType",
      "locationX": 40,
      "locationY": 600,
      "object": "_System_RecordType",
      "filterLogic": "and",
      "filters": [
        {
          "field": "ObjectId",
          "operator": "EqualTo",
          "value": {
            "elementReference": "$quoteObjectMetadata.Id"
          }
        },
        {
          "field": "Name",
          "operator": "EqualTo",
          "value": {
            "elementReference": "$sourceOpportunityRecordType.Name"
          }
        },
        {
          "field": "IsActive",
          "operator": "EqualTo",
          "value": true
        }
      ],
      "outputReference": "$quoteRecordType",
      "getFirstRecordOnly": true,
      "connector": {
        "targetReference": "GetOpportunityLineItems"
      }
    },
    {
      "name": "GetOpportunityLineItems",
      "label": "Get Opportunity line items",
      "locationX": 40,
      "locationY": 720,
      "object": "OpportunityLineItem",
      "filterLogic": "and",
      "filters": [
        {
          "field": "OpportunityId",
          "operator": "EqualTo",
          "value": {
            "elementReference": "opportunityId"
          }
        }
      ],
      "outputReference": "$opportunityLineItems",
      "getFirstRecordOnly": false,
      "connector": {
        "targetReference": "CreateQuote"
      }
    }
  ],
  "decisions": [
    {
      "name": "ValidateOpportunityExists",
      "label": "Reject if opportunityId does not resolve",
      "locationX": 220,
      "locationY": 240,
      "rules": [
        {
          "name": "OpportunityNotFound",
          "conditionLogic": "and",
          "conditions": [
            {
              "leftValueReference": "$opportunity.Id",
              "operator": "IsBlank"
            }
          ],
          "connector": {
            "targetReference": "FailInvalidOpportunityId"
          }
        }
      ],
      "defaultConnector": {
        "targetReference": "GetSourceOpportunityRecordType"
      }
    }
  ],
  "customErrors": [
    {
      "name": "FailInvalidOpportunityId",
      "label": "Invalid opportunityId supplied",
      "locationX": 400,
      "locationY": 240,
      "customErrorMessages": [
        {
          "errorMessage": "opportunityId does not refer to an Opportunity the current user can access",
          "statusCode": "MALFORMED_ID"
        }
      ]
    }
  ],
  "recordCreates": [
    {
      "name": "CreateQuote",
      "label": "Create Quote from Opportunity",
      "locationX": 40,
      "locationY": 840,
      "object": "Quote",
      "fieldMapping": {
        "sourceObject": "Opportunity",
        "sourceReference": "$opportunity",
        "targetObject": "Quote",
        "actionType": "createQuote"
      },
      "inputAssignments": [
        {
          "field": "OpportunityId",
          "value": {
            "elementReference": "opportunityId"
          }
        },
        {
          "field": "RecordTypeId",
          "value": {
            "elementReference": "$quoteRecordType.Id"
          }
        },
        {
          "field": "Status",
          "value": "Draft"
        }
      ],
      "assignRecordIdToReference": "quoteId",
      "connector": {
        "targetReference": "CopyOpportunityLineItems"
      }
    },
    {
      "name": "CreateQuoteLineItem",
      "label": "Create QuoteLineItem from OpportunityLineItem",
      "locationX": 220,
      "locationY": 1080,
      "object": "QuoteLineItem",
      "fieldMapping": {
        "sourceObject": "OpportunityLineItem",
        "sourceReference": "$currentOpportunityLineItem",
        "targetObject": "QuoteLineItem",
        "actionType": "createQuote"
      },
      "inputAssignments": [
        {
          "field": "QuoteId",
          "value": {
            "elementReference": "quoteId"
          }
        }
      ],
      "connector": {
        "targetReference": "CopyOpportunityLineItems"
      }
    }
  ],
  "loops": [
    {
      "name": "CopyOpportunityLineItems",
      "label": "Copy OpportunityLineItems",
      "locationX": 40,
      "locationY": 960,
      "collectionReference": "$opportunityLineItems",
      "assignNextValueToReference": "$currentOpportunityLineItem",
      "iterationOrder": "Asc",
      "nextValueConnector": {
        "targetReference": "CreateQuoteLineItem"
      }
    }
  ]
}
