public static bool CreateMgtFeeTransactions(BatchExecutionResults results, int[] mgtPeriodIds, int year, int quarter, ManagementTypes managementType, bool createCashInitiatedOrders)
        {
            IDalSession session = NHSessionFactory.CreateSession();

            DateTime minDate, maxDate;
            Util.GetDatesFromQuarter(year, quarter, out minDate, out maxDate);
            int mgtPeriodId = 0;
            int journalID = int.Parse((string)(System.Configuration.ConfigurationManager.AppSettings.Get("DefaultManagementFeeJournal")));
            IJournal journalMgmtFee = JournalMapper.GetJournal(session, journalID);
            IGLLookupRecords lookups = GlLookupRecordMapper.GetGLLookupRecords(session, BookingComponentParentTypes.ManagementFee);

            if (mgtPeriodIds != null && mgtPeriodIds.Length > 0)
            {
                FeeFactory feeFactory = FeeFactory.GetInstance(session, FeeFactoryInstanceTypes.Fee, true);
                decimal taxPercentage = feeFactory.GetHistoricalTaxRate(maxDate).StandardRate;

                for (int i = 0; i < mgtPeriodIds.Length; i++)
                {
                    try
                    {
                        mgtPeriodId = mgtPeriodIds[i];
                        if (createMgtFeeTransactionForMP(journalMgmtFee, lookups, mgtPeriodId, year, quarter, managementType, feeFactory, minDate, maxDate, taxPercentage, createCashInitiatedOrders))
                            results.MarkSuccess();
                    }
                    catch (Exception ex)
                    {
                        results.MarkError(
                            new ApplicationException(string.Format("Error creating management fee transaction for management period {0}.", mgtPeriodId), ex));
                    }
                }
            }
            session.Close();
            return true;
        }
示例#2
0
        public static void CreateNotaFromOrder(BatchExecutionResults results, int orderId)
        {
            IDalSession session = NHSessionFactory.CreateSession();

            try
            {
                ISecurityOrder order = OrderMapper.GetOrder(session, orderId) as ISecurityOrder;
                if (order != null)
                {
                    INota nota = order.CreateNota();
                    if (nota != null)
                    {
                        NotaMapper.Update(session, nota);
                        results.MarkSuccess();
                    }
                }
                else
                    results.MarkError(new ApplicationException(string.Format("Security Order {0} not found.", orderId)));
            }
            catch (Exception ex)
            {
                results.MarkError(new ApplicationException(string.Format("Error creating nota for order {0}.", orderId), ex));
            }
            finally
            {
                session.Close();
            }
        }
示例#3
0
        public static bool CreateDepartureInstructions(BatchExecutionResults results, int[] accountIds, DateTime executionDate, int? counterAccountID, string transferDescription, bool noCharges)
        {
            bool retVal = false;
            if (accountIds == null || accountIds.Count() == 0)
                throw new B4F.TotalGiro.ApplicationLayer.Common.GridviewNoSelectionException();

            using (IDalSession session = NHSessionFactory.CreateSession())
            {
                ICounterAccount counterAcc = null;
                if (counterAccountID.HasValue && counterAccountID.Value != 0)
                    counterAcc = CounterAccountMapper.GetCounterAccount(session, counterAccountID.Value);

                IList<IAccountTypeCustomer> accounts = AccountMapper.GetAccounts<IAccountTypeCustomer>(session, accountIds);
                if (accounts != null && accounts.Count > 0)
                {
                    IList saveAccounts = new ArrayList();
                    foreach (IAccountTypeCustomer account in accounts)
                    {
                        try
                        {
                            int? withdrawalCount = account.ActiveWithdrawalInstructions.GetV(e => e.Count);
                            if (withdrawalCount.HasValue && withdrawalCount.Value > 0)
                                throw new ApplicationException(string.Format("{0} withdrawal instructions exist and need to be cancelled before the clients portfolio can be liquidated.", withdrawalCount.Value));

                            IClientDepartureInstruction instruction = account.CreateDepartureInstruction(executionDate, counterAcc, transferDescription, noCharges);
                            if (instruction != null)
                            {
                                saveAccounts.Add(account);
                                results.MarkSuccess();
                                if (instruction.CounterAccount == null)
                                    results.MarkWarning(string.Format("Account {0} does not have a default counter account. Please look up it's counter account otherwise the client can not be paid.", instruction.Account.DisplayNumberWithName));
                            }
                        }
                        catch (Exception ex)
                        {
                            results.MarkError(
                                new ApplicationException(string.Format("Error creating departure instruction  for {0}.", account.DisplayNumberWithName), ex));
                        }
                    }
                    retVal = AccountMapper.UpDateList(session, saveAccounts);
                }
            }
            return retVal;
        }
        public static void UpdateLifecycleModelToAge(BatchExecutionResults results)
        {
            using (IDalSession session = NHSessionFactory.CreateSession())
            {
                try
                {
                    IManagementCompany comp = LoginMapper.GetCurrentManagmentCompany(session);
                    IInternalEmployeeLogin employee = (IInternalEmployeeLogin)LoginMapper.GetCurrentLogin(session);

                    Hashtable parameters = new Hashtable();
                    if (!comp.IsStichting)
                    {
                        IAssetManager am = (IAssetManager)comp;
                        if (!am.SupportLifecycles)
                            throw new ApplicationException("This asset manager does not support lifecycles.");
                        else
                            parameters.Add("managementCompanyID", am.Key);
                    }

                    List<ILifecycle> cycles = session.GetTypedListByNamedQuery<ILifecycle>(
                        "B4F.TotalGiro.Instruments.ActiveLifecycles",
                        parameters);

                    List<ILifecycleLine> lines = cycles.SelectMany(x => x.Lines).ToList();

                    List<Object> accountWithLifecycleData = session.GetTypedListByNamedQuery<Object>(
                        "B4F.TotalGiro.Instruments.AccountWithLifecycleData",
                        parameters);

                    var acctData = from a in accountWithLifecycleData.Cast<object[]>()
                                   where (DateTime)(a[4] ?? a[5] ?? DateTime.MinValue) != DateTime.MinValue
                                   select new
                                   {
                                       AccountID = (int)a[0],
                                       ModelID = (int)(a[2] ?? 0),
                                       LifecycleID = (int)a[3],
                                       Age = Util.CalculateCurrentAge((DateTime)(a[4] ?? a[5]))
                                   };

                    var acctNoBirthDate = from a in accountWithLifecycleData.Cast<object[]>()
                                          where (DateTime)(a[4] ?? a[5] ?? DateTime.MinValue) == DateTime.MinValue
                                          select (string)a[1];

                    if (acctNoBirthDate.Count() > 0)
                        results.MarkWarning(string.Format("{0} accounts have a primary account holder without a proper birth date: {1}",
                            acctNoBirthDate.Count(),
                            acctNoBirthDate.Take(25).JoinStrings(",")));

                    var acctIds = from x in acctData
                                  join y in lines on x.LifecycleID equals y.Parent.Key
                                  where x.Age >= y.AgeFrom && x.Age < y.AgeTo && x.ModelID != y.Model.Key
                                  select new { x.AccountID, x.Age }; //, x.Age, x.ModelID, y.AgeFrom, y.AgeTo, y.Model.ModelName };

                    foreach (var acctId in acctIds)
                    {
                        ICustomerAccount acc = (ICustomerAccount)AccountMapper.GetAccount(session, acctId.AccountID);
                        if (acc.IsDeparting)
                            results.MarkWarning(string.Format("Account {0} is departing so the model will not be updated", acc.DisplayNumberWithName));
                        else if (acc.IsUnderRebalance)
                            results.MarkWarning(string.Format("Account {0} is under rebalance so the model will not be updated", acc.DisplayNumberWithName));
                        else
                        {
                            ILifecycle lc = acc.Lifecycle;
                            IPortfolioModel model = null;
                            if (lc != null)
                            {
                                model = lc.GetRelevantModel(acctId.Age);
                                if (!acc.ModelPortfolio.Equals(model))
                                    acc.SetModelPortfolio(acc.Lifecycle, model, acc.IsExecOnlyCustomer, acc.EmployerRelationship, employee, DateTime.Now);
                                if (AccountMapper.Update(session, acc))
                                    results.MarkSuccess();
                            }
                            else
                                results.MarkError(
                                    new ApplicationException(string.Format("Account {0} did not have a lifecycle.", acc.DisplayNumberWithName)));
                        }
                    }
                }
                catch (Exception ex)
                {
                    results.MarkError(
                        new ApplicationException("Error in UpdateLifecycleModelToAge.", ex));
                }
            }
        }
        private static bool CreatePeriodicWithdrawals(BatchExecutionResults results, int[] keys, DateTime endDate)
        {
            ICustomerAccount account = null;
            IDalSession session = null;

            if (keys != null && keys.Length > 0)
            {
                for (int j = 0; j < keys.Length; j++)
                {
                    int ruleKey = keys[j];
                    int itemsCreated = 0;
                    try
                    {
                        session = NHSessionFactory.CreateSession();

                        Hashtable parameters = new Hashtable(1);
                        parameters.Add("withdrawalRuleId", ruleKey);

                        IList<IWithdrawalRule> rules = session.GetTypedListByNamedQuery<IWithdrawalRule>(
                            "B4F.TotalGiro.Accounts.Withdrawals.GetWithdrawalRule",
                            parameters);

                        if (rules != null && rules.Count == 1)
                        {
                            IWithdrawalRule rule = rules[0];
                            account = rule.Account;

                            if (!account.IsDeparting)
                            {
                                DateTime maxDate;

                                // if not passed in -> get the max date
                                if (endDate == DateTime.MinValue)
                                    maxDate = rule.GetMaxWithdrawalDate();
                                else
                                {
                                    if (Util.IsNotNullDate(rule.EndDateWithdrawal) && endDate > rule.EndDateWithdrawal)
                                        maxDate = rule.EndDateWithdrawal;
                                    else
                                        maxDate = endDate;
                                }
                                bool isDirty = false;
                                int start = (rule.LastWithdrawalDate >= DateTime.Today ? 0 : 1);

                                // hardcoded: Never look further then 12 months
                                for (int i = start; i < (12 + start); i++)
                                {
                                    DateTime nextDate = rule.GetSpecificDate(i);
                                    if (Util.IsNullDate(nextDate) || nextDate > maxDate)
                                        break;

                                    if (!rule.WithdrawalInstructions.Contains(nextDate))
                                    {
                                        // periodic withdrawal is always without commission
                                        account.CreateWithdrawalInstruction(DateTime.Today, nextDate, rule.Amount.Negate(), null, rule, null, rule.DoNotChargeCommission);
                                        isDirty = true;
                                        itemsCreated++;
                                    }
                                }
                                if (isDirty)
                                {
                                    AccountMapper.Update(session, account);
                                    results.MarkSuccess(itemsCreated);
                                }
                            }
                            else
                                results.MarkError(
                                    new ApplicationException(string.Format("Did not create periodic Withdrawal Instruction  for {0} since the account is departing.", (account != null ? account.DisplayNumberWithName : ruleKey.ToString()))));
                        }
                    }
                    catch (Exception ex)
                    {
                        results.MarkError(
                            new ApplicationException(string.Format("Error creating periodic Withdrawal Instruction  for {0}.", (account != null ? account.DisplayNumberWithName : ruleKey.ToString())), ex));
                    }
                }
            }

            if (session != null)
                session.Close();
            return true;
        }
示例#6
0
        public static bool CreateRebalanceInstructions(BatchExecutionResults results, int[] accountIds, OrderActionTypes orderActionType, bool noCharges, DateTime execDate, List<RebalanceExclusionDetails> exclusions)
        {
            bool retVal = false;

            if (accountIds == null || accountIds.Count() == 0)
                throw new B4F.TotalGiro.ApplicationLayer.Common.GridviewNoSelectionException();

            using (IDalSession session = NHSessionFactory.CreateSession())
            {
                IList<IAccountTypeCustomer> accounts = AccountMapper.GetAccounts<IAccountTypeCustomer>(session, accountIds);
                if (accounts != null && accounts.Count > 0)
                {
                    IList saveAccounts = new ArrayList();
                    foreach (IAccountTypeCustomer account in accounts)
                    {
                        try
                        {
                            IRebalanceInstruction instruction = (IRebalanceInstruction)account.CreateInstruction(InstructionTypes.Rebalance, orderActionType, execDate, noCharges);
                            if (instruction != null)
                            {
                                if (exclusions != null && exclusions.Count > 0)
                                {
                                    foreach (RebalanceExclusionDetails exclusion in exclusions)
                                    {
                                        switch (exclusion.ComponentType)
                                        {
                                            case ModelComponentType.Model:
                                                if (exclusion.Model == null)
                                                    exclusion.Model = ModelMapper.GetModel(session, exclusion.ComponentKey);
                                                instruction.ExcludedComponents.AddExclusion(exclusion.Model);
                                                break;
                                            case ModelComponentType.Instrument:
                                                if (exclusion.Instrument == null)
                                                    exclusion.Instrument = InstrumentMapper.GetTradeableInstrument(session, exclusion.ComponentKey);
                                                instruction.ExcludedComponents.AddExclusion(exclusion.Instrument);
                                                break;
                                        }
                                    }
                                }
                                saveAccounts.Add(account);
                                results.MarkSuccess();
                            }
                        }
                        catch (Exception ex)
                        {
                            results.MarkError(
                                new ApplicationException(string.Format("Error creating rebalance instruction  for {0}.", account.DisplayNumberWithName), ex));
                        }
                    }
                    retVal = AccountMapper.UpDateList(session, saveAccounts);
                }
            }
            return retVal;
        }
示例#7
0
        public static bool CreateWithdrawalInstructions(BatchExecutionResults results, int[] accountIds, DateTime executionDate, DateTime withdrawalDate, decimal withdrawalAmount, int? counterAccountID, string transferDescription, bool noCharges)
        {
            bool retVal = false;
            if (accountIds == null || accountIds.Count() == 0)
                throw new B4F.TotalGiro.ApplicationLayer.Common.GridviewNoSelectionException();

            using (IDalSession session = NHSessionFactory.CreateSession())
            {
                if (withdrawalAmount == 0)
                    throw new ApplicationException("The amount can not be zero");

                ICounterAccount counterAcc = null;
                if (counterAccountID.HasValue && counterAccountID.Value != 0)
                {
                    counterAcc = CounterAccountMapper.GetCounterAccount(session, counterAccountID.Value);
                    if (counterAcc == null)
                        throw new ApplicationException("Counter Account can not be found.");
                }

                ICurrency baseCurrency = LoginMapper.GetCurrentManagmentCompany(session).BaseCurrency;
                Money amount = new Money(withdrawalAmount, baseCurrency).Negate();

                IList<IAccountTypeCustomer> accounts = AccountMapper.GetAccounts<IAccountTypeCustomer>(session, accountIds);
                if (accounts != null && accounts.Count > 0)
                {
                    IList saveAccounts = new ArrayList();
                    foreach (IAccountTypeCustomer account in accounts)
                    {
                        try
                        {
                            if (account.CreateWithdrawalInstruction(executionDate, withdrawalDate, amount, counterAcc, null, transferDescription, noCharges) != null)
                            {
                                saveAccounts.Add(account);
                                results.MarkSuccess();
                            }
                        }
                        catch (Exception ex)
                        {
                            results.MarkError(
                                new ApplicationException(string.Format("Error creating withdrawal instruction  for {0}.", account.DisplayNumberWithName), ex));
                        }
                    }
                    retVal = AccountMapper.UpDateList(session, saveAccounts);
                }
            }
            return retVal;
        }
        public static bool SkipAverageHoldingCorrections(BatchExecutionResults results, int[] avgHoldingIds, ManagementTypes managementType)
        {
            IDalSession session = NHSessionFactory.CreateSession();

            if (avgHoldingIds != null && avgHoldingIds.Length > 0)
            {
                try
                {
                    IList list = ManagementPeriodUnitMapper.GetManagementPeriodUnitCorrections(session, avgHoldingIds, managementType);
                    if (list != null)
                    {
                        int counter = 0;
                        foreach (IManagementPeriodUnitCorrection correction in list)
                        {
                            correction.Skip = true;
                            counter++;
                        }

                        if (session.Update(list))
                            results.MarkSuccess(counter);
                    }
                }
                catch (Exception ex)
                {
                    results.MarkError(
                        new ApplicationException("Error skipping average holding corrections.", ex));
                }
            }
            session.Close();
            return true;
        }
示例#9
0
        private static void exportGrouping(BatchExecutionResults results, IDalSession session, ILedgerType ledgerType, DateTime dateUntil,
                                           string exportFilePath)
        {
            try
            {
                string fileName = string.Format("{0}_{1:yyyyMMdd}", ledgerType.Type, dateUntil);
                string fileExt = "csv";

                IList ledgerEntries = LedgerEntryMapper.GetLedgerEntries(session, ledgerType, dateUntil);
                int fileOrdinal = ExportedLedgerFileMapper.GetNextOrdinal(session, fileName);

                if ((ledgerEntries != null) && (ledgerEntries.Count > 0))
                {
                    ExportedLedgerFile exportedLedgerFile = new ExportedLedgerFile(fileName, fileExt, exportFilePath, fileOrdinal++);
                    FileStream fs = new FileStream(exportedLedgerFile.FullPathName, FileMode.Create);
                    StreamWriter sw = new StreamWriter(fs);

                    foreach (ILedgerEntry ledgerEntry in ledgerEntries)
                    {
                        string formattedEntry = formatLedgerEntry(results, ledgerEntry);

                        if (formattedEntry.Length > 0)
                        {
                            sw.Write(formattedEntry);

                            ledgerEntry.ExportedLedgerFile = exportedLedgerFile;
                            exportedLedgerFile.LedgerEntries.AddLedgerEntry(ledgerEntry);
                        }
                    }

                    sw.Close();
                    fs.Close();
                    ExportedLedgerFileMapper.Update(session, exportedLedgerFile);
                    results.MarkSuccess();
                }
            }
            catch (Exception ex)
            {
                results.MarkError(
                    new ApplicationException(string.Format("Error exporting for ledger type '{0}', currency '{1}' and transaction date {2:d}.",
                                                           ledgerType.Type, dateUntil), ex));
            }
        }
示例#10
0
        private static void sendEmailNotificationsToContacts(BatchExecutionResults results, List<IContact> contacts, List<IDocument> documents,
                                                             DocumentSubtypes documentSubtype)
        {
            if (contacts.Count > 0)
            {
                ICustomerAccount account = documents[0].Account;

                string body = documentsCreatedEmailTemplate;
                body = Utility.ShowOptionalTag(body, "option-notas", documentSubtype == DocumentSubtypes.Notas);
                body = Utility.ShowOptionalTag(body, "option-reports", documentSubtype == DocumentSubtypes.QuarterlyReports ||
                                                                       documentSubtype == DocumentSubtypes.YearlyReports);

                string clientWebsiteUrl = (account.AccountOwner.StichtingDetails.ClientWebsiteUrl ?? "").TrimEnd('/');
                if (string.IsNullOrEmpty(clientWebsiteUrl))
                    throw new ApplicationException("Client Website URL not known.");

                body = body.Replace("<%AccountNumber%>", account.Number)
                           .Replace("<%ClientWebsiteUrl%>", clientWebsiteUrl);

                MailMessage message = new MailMessage();
                message.Subject = string.Format("Nieuwe {0} portefeuille {1}",
                                                documentSubtype == DocumentSubtypes.Notas ? "transactienota’s" : "rapportage",
                                                account.Number);
                message.IsBodyHtml = true;

                SmtpClient client = new SmtpClient();

                foreach (IContact contact in contacts)
                {
                    message.To.Clear();
                    message.To.Add(testEmailRecipients != "" ? testEmailRecipients : contact.Email);
                    message.Body = body.Replace("<%DearSirForm%>", contact.CurrentNAW.Formatter.DearSirForm);

                    client.Send(message);
                    results.MarkSuccess();
                }
            }
        }
示例#11
0
        private static void createNotaFromTransaction(BatchExecutionResults results, int transactionId, TransactionTypes transactionType)
        {
            IDalSession session = NHSessionFactory.CreateSession();

            try
            {
                ITransaction transaction = TransactionMapper.GetTransaction(session, transactionId);
                if (transaction != null)
                {
                    INota nota = transaction.CreateNota();
                    if (nota != null)
                    {
                        NotaMapper.Update(session, nota);
                        results.MarkSuccess();
                    }
                    else
                        // in case NotaMigrated was set to 'true' (e.g. for a storno of a Monetary Order transaction)
                        TransactionMapper.Update(session, transaction);
                }
                else
                    results.MarkError(new ApplicationException(string.Format("Transaction {0} not found.", transactionId)));
            }
            catch (Exception ex)
            {
                results.MarkError(new ApplicationException(string.Format("Error creating nota for transaction {0} ({1}).",
                                                                                       transactionId, transactionType), ex));
            }
            finally
            {
                session.Close();
            }
        }
示例#12
0
        private static void createNotaFromBooking(BatchExecutionResults results, int bookingId, GeneralOperationsBookingReturnClass bookingType)
        {
            IDalSession session = NHSessionFactory.CreateSession();

            try
            {
                IGeneralOperationsBooking booking = GeneralOperationsBookingMapper.GetBooking(session, bookingId);
                if (booking != null)
                {
                    INota nota = booking.CreateNota();
                    if (nota != null)
                    {
                        NotaMapper.Update(session, nota);
                        results.MarkSuccess();
                    }
                    else
                        // in case NotaMigrated was set to 'true' (e.g. for a storno of a Monetary Order booking)
                        GeneralOperationsBookingMapper.Update(session, booking);
                }
                else
                    results.MarkError(new ApplicationException(string.Format("Booking {0} not found.", bookingId)));
            }
            catch (Exception ex)
            {
                results.MarkError(new ApplicationException(string.Format("Error creating nota for booking {0} ({1}).",
                                                                                       bookingId, bookingType), ex));
            }
            finally
            {
                session.Close();
            }
        }
示例#13
0
        private void printNotasForAccount(BatchExecutionResults results, int accountId, ReportExecutionWrapper reportExecutionWrapper,
                                          string pdfOnlineReportsFolder, string pdfPostReportsFolder, bool showLogo)
        {
            using (IDalSession session = NHSessionFactory.CreateSession())
            {
                try
                {
                    List<INota> notas = NotaMapper.GetUnprintedNotasByAccount(session, accountId, NotaType);
                    if (notas.Count > 0)
                    {
                        ICustomerAccount account = notas[0].Account;
                        foreach (INota[] notaGroup in ReportGrouping.GetGroups(notas))
                        {
                            try
                            {
                                DataSet ds = buildDataSet(session, notaGroup);

                                string pdfFileName = string.Format(@"{0}_{1:d4}_{2}_{3}.pdf",
                                                                   account.Number,
                                                                   account.AccountHolders.PrimaryAccountHolder.Contact.Key,
                                                                   notaGroup[0].NotaNumber,
                                                                   GetFileSuffix(notaGroup));
                                string pdfOnlineFullPath = string.Format(@"{0}\{1}", pdfOnlineReportsFolder, pdfFileName),
                                       pdfPostFullPath = string.Format(@"{0}\{1}", pdfPostReportsFolder, pdfFileName);

                                List<string> paramValues = new List<string>();
                                GenerateParamValues(paramValues, showLogo, notaGroup);

                                List<string> paramValuesWithShowLogo = copyParamValuesWithShowLogo(paramValues, reportExecutionWrapper.ExtraParamNames);

                                reportExecutionWrapper.Run(ds, pdfOnlineFullPath, paramValuesWithShowLogo.ToArray());

                                bool needsSendByPost = account.NeedsSendByPost(SendableDocumentCategories.NotasAndQuarterlyReports);
                                if (needsSendByPost)
                                {
                                    if (showLogo)
                                        File.Copy(pdfOnlineFullPath, pdfPostFullPath, true);
                                    else
                                        reportExecutionWrapper.Run(ds, pdfPostFullPath, paramValues.ToArray());
                                }

                                registerNotaPrinting(session, notaGroup, pdfFileName, pdfOnlineReportsFolder, needsSendByPost);
                                results.MarkSuccess(notaGroup.Length);
                            }
                            catch (Exception ex)
                            {
                                results.MarkError(new ApplicationException(
                                    string.Format("Error printing nota's ({0}) for account {1} ({2}), in PDF file containing nota number {3}.",
                                                  NotaType.ToString(), account.DisplayNumberWithName, accountId,
                                                  notaGroup[0].NotaNumber), ex));
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    ICustomerAccount errAccount = AccountMapper.GetAccount(session, accountId) as ICustomerAccount;
                    string accountNumberWithName = (errAccount != null ? errAccount.DisplayNumberWithName : "");
                    results.MarkError(new ApplicationException(string.Format("Error retrieving nota's ({0}) for account {1} ({2}).",
                                                                             NotaType.ToString(), accountNumberWithName, accountId), ex));
                }
            }
        }