public TrackedDocument GetDisclosuresTrackedDoc(string eFolderNameThatContainsPackage, WCMDisclosurePackage package)
        {
            LogEntryList docList = Loan.Log.TrackedDocuments.GetDocumentsByTitle(eFolderNameThatContainsPackage);

            if (docList.Count == 0)
            {
                throw new WCMException(
                          $"No placeholder was found '{eFolderNameThatContainsPackage}'. " +
                          $"Please re-generate disclosure package");
            }
            else if (docList.Count > 1)
            {
                // which placeholder do we choose? try to remove empty ones first
                EncompassUtilities.RemoveEmptyDuplicatePlaceholder(docList, this.Loan);
            }

            //after removing empty placeholders, if still more than 1, fail
            docList = Loan.Log.TrackedDocuments.GetDocumentsByTitle(eFolderNameThatContainsPackage);
            if (docList.Count > 1)
            {
                throw new WCMException(
                          $"More than one '{eFolderNameThatContainsPackage}' placeholder with attachments. " +
                          $"Please contact tech support.");
            }

            // now grab attachments and save them to CDO
            return((TrackedDocument)docList[0]);

            //AddDisclosuresToCdoResponse addDisclosuresToCdoResult = AddDisclosuresToCustomDataObject(this.Loan, eFolderPlaceholderContainingDisclosures, package.PackageType);
            //if (addDisclosuresToCdoResult.WasSuccessful == false)
            //{
            //    throw new WCMException(
            //        $"Error adding disclosures to CDO. {addDisclosuresToCdoResult.ErrorMessage}.");
            //}

            //EncompassUtilities.DeleteAttachmentsFromEfolder(this.Loan, eFolderPlaceholderContainingDisclosures);

            //return addDisclosuresToCdoResult.OrderToBeSent;
        }
        public AddTitleOnlyPartyResponse CreateTitleOnlyPartyPortal(int tpoIndex)
        {
            var loan = this.Loan;
            var titleOnlyPartyIdField = loan.Fields[$"CX.BLEND.TPO.ID{tpoIndex}"];

            if (titleOnlyPartyIdField.IsEmpty() == false)
            {
                Macro.Alert("ERROR: A Blend Portal has already been created for this Title Only Party. Please try to create one on a different line.");
                return(null);
            }

            AddTitleOnlyPartyResponse response = new AddTitleOnlyPartyResponse();

            List <string> fieldIdsThatMustBeFilledOut = new List <string>()
            {
                $"CX.BLEND.TPO.FIRSTNAME{tpoIndex}",
                $"CX.BLEND.TPO.LASTNAME{tpoIndex}",
                $"CX.BLEND.TPO.EMAIL{tpoIndex}",
                $"CX.BLEND.TPO.SIGNERTYPE{tpoIndex}"
            };

            List <LoanField> emptyFields = new List <LoanField>();

            foreach (var item in fieldIdsThatMustBeFilledOut)
            {
                var field = loan.Fields[item];
                if (field.IsEmpty())
                {
                    emptyFields.Add(field);
                }
            }

            if (emptyFields.Any())
            {
                var fieldIds = emptyFields.Select(x => x.ID).ToList();
                EncompassUtilities.HighlightEmptyFields(fieldIds, this.Form, loan);

                string fieldDescriptions = string.Join(", ", emptyFields.Select(x => x.Descriptor).ToList());
                Macro.Alert($"Error Creating Third Party Portal{Environment.NewLine + Environment.NewLine}Required fields are empty: {fieldDescriptions}.");

                return(null);
            }


            string tpoFirstName = loan.Fields[$"CX.BLEND.TPO.FIRSTNAME{tpoIndex}"].Value.ToString();
            string tpoLastName  = loan.Fields[$"CX.BLEND.TPO.LASTNAME{tpoIndex}"].Value.ToString();
            string email        = loan.Fields[$"CX.BLEND.TPO.EMAIL{tpoIndex}"].Value.ToString();
            string vestingType  = loan.Fields[$"CX.BLEND.TPO.SIGNERTYPE{tpoIndex}"].Value.ToString();


            // get blend parties before creating tpo
            var getPartiesResponse = BlendUtility.GetPartiesOnLoan(BlendUtility.GetPortalId(loan), WcmSettings.BlendSettings.GetAllLoanPartiesUri);

            if (getPartiesResponse.WasSuccessful == false)
            {
                response.ErrorMessage  = $"Error Creating Third Party Portal{Environment.NewLine + Environment.NewLine}Error retreiving loan parties. '{getPartiesResponse.ErrorMessage}'.";
                response.WasSuccessful = false;
                return(response);
            }

            List <LoanParty> loanPartiesBeforeCommit = getPartiesResponse.LoanParties;
            //  Macro.Alert(loanPartiesBeforeCommit.Count + " Parties Before Commit");

            // need to map WCM 'vesting type' value to Ellie Mae's values

            Dictionary <string, string> vestingDictionary = new Dictionary <string, string>();

            // WCM field value, encompass value
            vestingDictionary.Add("OTHER", "");
            vestingDictionary.Add("SETTLOR", "Title Only Settlor Trustee");
            vestingDictionary.Add("SPOUSE", "Non Title Spouse");
            vestingDictionary.Add("TITLE_HOLDER", "Title only");
            vestingDictionary.Add("TITLE_HOLDER_TRUSTEE", "Title Only Trustee");

            var thisVesting = vestingDictionary.Where(x => x.Key.Equals(vestingType)).FirstOrDefault();

            if (string.IsNullOrEmpty(thisVesting.Value))
            {
                Macro.Alert($"Error Creating Third Party Portal{Environment.NewLine + Environment.NewLine}ERROR: Unable to map vesting party '{vestingType}' for Blend.");
                return(null);
            }
            //check for entry in borrower Information - Vesting screen prior to mapping to file contacts and remove if entry is same as third Party being created
            bool   doesVestingEntryExist = false;
            int    vestingIndex          = loan.AdditionalVestingParties.Count;
            string tpoName = tpoFirstName + " " + tpoLastName;

            if (loan.Fields[$"TR0{vestingIndex}01"].ToString().Equals(tpoName, StringComparison.OrdinalIgnoreCase))
            {
                doesVestingEntryExist = true;
            }
            // grab SSN and DOB before deleting to include in FileContact/ newly created Vesting
            string ssnVestedParty = loan.Fields[$"TR0{vestingIndex}03"].GetStringValueBlankIfNull();
            string dobVestedParty = loan.Fields[$"TR0{vestingIndex}12"].GetStringValueBlankIfNull();

            if (doesVestingEntryExist)
            {
                loan.AdditionalVestingParties.RemoveAt(vestingIndex);
            }

            // create non-borrowering owner contact programatically
            int contactIndex = loan.NBOContacts.Add();

            loan.Fields[$"NBOC0{contactIndex}01"].Value = tpoFirstName;
            loan.Fields[$"NBOC0{contactIndex}03"].Value = tpoLastName;
            loan.Fields[$"NBOC0{contactIndex}11"].Value = email;
            loan.Fields[$"NBOC0{contactIndex}09"].Value = thisVesting.Value;
            loan.Fields[$"NBOC0{contactIndex}16"].Value = dobVestedParty;

            List <LoanParty> loanPartiesAfterCommit = new List <LoanParty>();

            // when 'commit' is called, KM's bridge plugin will create title only party in Blend
            // there is a chance that the creating the Title only party, commiting, and getting parties again from blend
            // happens so fast, we won't get new party created. Creating a loop to try this sequence 3 times and wait a few seconds between each one
            for (int i = 0; i < 4; i++)
            {
                loan.Commit();
                loan.Fields[$"TR0{vestingIndex}03"].Value = ssnVestedParty;


                // get blend parties after creating tpo and we should have 1 more....
                getPartiesResponse = BlendUtility.GetPartiesOnLoan(BlendUtility.GetPortalId(loan), WcmSettings.BlendSettings.GetAllLoanPartiesUri);
                if (getPartiesResponse.WasSuccessful == false)
                {
                    string msg = $"Error Creating Third Party Portal{Environment.NewLine + Environment.NewLine}{loan.LoanNumber}Error retreiving loan parties. '{getPartiesResponse.ErrorMessage}'.";
                    response.WasSuccessful = false;
                    response.ErrorMessage  = msg;
                    Macro.Alert(msg);
                    return(response);
                }

                loanPartiesAfterCommit = getPartiesResponse.LoanParties;

                //Macro.Alert(loanPartiesAfterCommit.Count + " Parties");
                if (loanPartiesBeforeCommit.Count != loanPartiesAfterCommit.Count)
                {
                    // sucess! This means titl only party was created, so continue
                    break;
                }
                if (loanPartiesAfterCommit.Count == loanPartiesAfterCommit.Count)
                {
                    System.Threading.Thread.Sleep(TimeSpan.FromSeconds(3));
                }
            }

            if (loanPartiesAfterCommit.Count == loanPartiesBeforeCommit.Count)
            {
                response.WasSuccessful = false;
                string msg = $"Error Creating Third Party Portal{Environment.NewLine + Environment.NewLine}{loan.LoanNumber}. The number of loan parties in Blend is the same as after trying to create Title Only Party. This is a big issue. Please submit a tech request.";
                response.ErrorMessage = msg;
                Macro.Alert(msg);
                return(response);
            }


            // find new loan party
            foreach (var party in loanPartiesBeforeCommit)
            {
                var borrower = loanPartiesAfterCommit.Where(x => x.id.Equals(party.id, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                if (borrower != null)
                {
                    loanPartiesAfterCommit.Remove(borrower);
                }
            }

            if (loanPartiesAfterCommit.Count != 1)
            {
                response.WasSuccessful = false;
                string msg = $"Error Creating Third Party Portal{Environment.NewLine + Environment.NewLine}{loan.LoanNumber}. There are '{loanPartiesAfterCommit}' new loan parties. We should only have 1. This is a problem. Please submit a tech request.";
                response.ErrorMessage = msg;
                Macro.Alert(msg);
                return(response);
            }


            // this is our new loan party
            var titleOnlyParty = loanPartiesAfterCommit[0];

            titleOnlyPartyIdField.Value = titleOnlyParty.id;
            Macro.Alert($"True. {Environment.NewLine + Environment.NewLine}Third Party Portal Created Succesfully. Party ID: {titleOnlyParty.id}.");


            return(response);
        }