Esempio n. 1
0
        public ActionResult <bool> PersistProfile([FromBody] dynamic createdProfile)
        {
            ProfileDataProcessing profileDataAccessComponent = new ProfileDataProcessing(_dbCtx);
            bool profileIsCreated = profileDataAccessComponent.SaveProfile(MapToProfile(createdProfile, true));

            return(Ok(profileIsCreated));
        }
Esempio n. 2
0
        public ActionResult <bool> UpdateProfile([FromBody] dynamic editedProfile)
        {
            ProfileDataProcessing profileDataAccessComponent = new ProfileDataProcessing(_dbCtx);
            bool isOkUpdate = profileDataAccessComponent.UpdateProfile(MapToProfile(editedProfile));

            if (isOkUpdate)
            {
                Log.Information("Profile successfully updated for ticker: " + editedProfile.tickerSymbol);
            }

            return(Ok(isOkUpdate));
        }
Esempio n. 3
0
        public Profile BuildProfileForProjections(Profile profile, Data.PIMS3Context ctx)
        {
            profileToBeInitialized = profile;
            ProfileDataProcessing profileDataAccessComponent = new ProfileDataProcessing(ctx);

            // try-catch here, or done in data access component?
            profileToBeInitialized = profileDataAccessComponent.BuildProfile(profile.TickerSymbol.Trim());

            // Fetched dividend rate via 3rd party service is unreliable. Reinitializing frequency; needed.
            profileToBeInitialized.DividendFreq = profile.DividendFreq;
            CalculateDividendYield();

            return(profileToBeInitialized);
        }
Esempio n. 4
0
        public ActionResult <Profile> GetProfile(string ticker, bool useDb, string loggedInName)
        {
            ProfileDataProcessing profileDataAccessComponent = new ProfileDataProcessing(_dbCtx);

            try
            {
                IQueryable <Profile> dBProfile = profileDataAccessComponent.FetchDbProfile(ticker, loggedInName);
                return(Ok(dBProfile));  // dBProfile : null || valid Profile.
            }
            catch
            {
                Log.Warning("No Db profile found for {0}; expected outcome if duplicate profile check, otherwise potential error in ProfileController.GetProfile().", ticker);
                return(BadRequest(new { errorMsg = "Error fetching custom Profile." }));
            }
        }
Esempio n. 5
0
        public ActionResult <DistributionScheduleVm> GetDistributionSchedules(string loggedInvestorId)
        {
            ProfileDataProcessing profileDataAccessComponent = new ProfileDataProcessing(_dbCtx);

            try
            {
                var profileSchedules = profileDataAccessComponent.FetchProfileDividendSchedules(loggedInvestorId);
                return(Ok(profileSchedules));
            }
            catch (Exception)
            {
                Log.Warning("Error fetching profiles for {0}, via ProfileController.GetDistributionSchedules().", loggedInvestorId);
                return(BadRequest(new { errorMsg = "Error fetching custom Profile." }));
            }
        }
Esempio n. 6
0
        public ActionResult <string> UpdateAllProfiles(string investorLogin)
        {
            // Investor-initiated portfolio profile updates.
            string serializedBatchResponse = string.Empty;

            ProfileDataProcessing            profileDataAccessComponent = new ProfileDataProcessing(_dbCtx);
            ProfilesUpdateSummaryResultModel batchResponse = profileDataAccessComponent.BatchUpdateProfiles(investorLogin);

            if (batchResponse != null || batchResponse.ProcessedTickersCount > 0)
            {
                serializedBatchResponse = JsonConvert.SerializeObject(batchResponse);
                return(serializedBatchResponse);
            }
            else
            {
                Log.Error("Error updating Profiles via ProfileController.UpdateAllProfiles() for investor: " + investorLogin);
                return(string.Empty);
            }
        }
Esempio n. 7
0
        public Dictionary <string, string> CalculateDivFreqAndDivMonths(string tickerSymbol, Data.PIMS3Context ctx)
        {
            StringBuilder oneYearDivPayMonths_1 = new StringBuilder();
            string        oneYearDivPayMonths_2 = string.Empty;
            int           divFreqCounter        = 0;
            string        tempDate = "";

            var    profileDataAccessComponent = new ProfileDataProcessing(ctx);
            JArray orderedJsonTickerPriceData = profileDataAccessComponent.FetchDividendSpecsForTicker(tickerSymbol);

            if (orderedJsonTickerPriceData == null)
            {
                Log.Warning("ProfileProcessing.CalculateDivFreqAndDivMonths() - found unresolved ticker in Tiingo service, unable to update Profile price data for {0}: ", tickerSymbol);
                return(null);
            }

            List <int> divPayoutDays = new List <int>();

            foreach (JObject objChild in orderedJsonTickerPriceData.Children <JObject>())
            {
                // Loop will key in on "divCash" for gathering needed freq & month specs.
                foreach (var property in objChild.Properties())
                {
                    if (property.Name == "date")
                    {
                        tempDate = property.Value.ToString();
                    }

                    if (property.Name == "divCash")
                    {
                        if (decimal.Parse(property.Value.ToString()) > 0)
                        {
                            divFreqCounter += 1;
                            oneYearDivPayMonths_1.Append(ExtractMonthFromDivPayDate(tempDate));
                            divPayoutDays.Add(ExtractDivPayDay(tempDate));
                            oneYearDivPayMonths_1.Append(",");
                        }
                    }
                }
            }

            int medianDivPayoutDay = CommonSvc.CalculateMedianValue(divPayoutDays);

            if (oneYearDivPayMonths_1.Length == 0)
            {
                return(null);
            }

            // Strip trailing comma.
            oneYearDivPayMonths_2 = oneYearDivPayMonths_1.ToString().Substring(0, oneYearDivPayMonths_1.Length - 1);
            string[] oneYearDivPayMonths_3 = oneYearDivPayMonths_2.Split(',');

            Dictionary <string, string> finalProfileSpecs = new Dictionary <string, string>();
            int monthsCount = oneYearDivPayMonths_3.Length;

            /* == finalProfileSpecs Keys legend: ==
             *       "DF"(dividend frequency)
             *       "DM"(dividend months)
             *       "DPD"(dividend payout day)
             */

            if (monthsCount >= 3 && monthsCount <= 5)
            {
                // Due to possible inconsistent number of income receipts made within the last 12 month price history obtained
                // from our 3rd party service (Tiingo), we'll account for this by designating as (Q)uarterly dividend frequency.
                finalProfileSpecs.Add("DF", "Q");
                finalProfileSpecs.Add("DM", oneYearDivPayMonths_2);
            }
            else if (monthsCount >= 5)
            {
                finalProfileSpecs.Add("DF", "M");
                finalProfileSpecs.Add("DM", "-");
            }
            else if (monthsCount == 2)
            {
                finalProfileSpecs.Add("DF", "S");
                finalProfileSpecs.Add("DM", oneYearDivPayMonths_2);
            }
            else
            {
                finalProfileSpecs.Add("DF", "A");
                finalProfileSpecs.Add("DM", oneYearDivPayMonths_2);
            }

            if (medianDivPayoutDay > 0)
            {
                finalProfileSpecs.Add("DPD", medianDivPayoutDay.ToString());
            }

            return(finalProfileSpecs);
        }
Esempio n. 8
0
        public IEnumerable <AssetCreationVm> ParsePortfolioSpreadsheetForAssetRecords(string filePath, ImportFileDataProcessing dataAccessComponent, string id)
        {
            List <AssetCreationVm> assetsToCreateList  = new List <AssetCreationVm>();
            var             profileDataAccessComponent = new ProfileDataProcessing(_ctx);
            var             existingProfileId          = string.Empty;
            var             existingAssetClassId       = "6215631D-5788-4718-A1D0-A2FC00A5B1A7";;
            var             newAssetId         = Guid.NewGuid().ToString();
            List <Position> positionsToBeSaved = null;

            try
            {
                string lastTickerProcessed = string.Empty;
                var    importFile          = new FileInfo(filePath);

                using (ExcelPackage package = new ExcelPackage(importFile))
                {
                    ExcelWorksheet  workSheet    = package.Workbook.Worksheets[0];
                    int             totalRows    = workSheet.Dimension.End.Row;
                    int             totalColumns = workSheet.Dimension.End.Column;
                    AssetCreationVm newAsset     = new AssetCreationVm();

                    // Iterate XLS/CSV, ignoring column headings (row 1).
                    for (var rowNum = 2; rowNum <= totalRows; rowNum++)
                    {
                        // Validate XLS
                        var headerRow = workSheet.Cells[1, 1, rowNum, totalColumns].Select(c => c.Value == null ? string.Empty : c.Value.ToString());
                        if (!ValidateFileType(filePath))
                        {
                            return(null);
                        }

                        // Args: Cells[fromRow, fromCol, toRow, toCol]
                        var row                         = workSheet.Cells[rowNum, 1, rowNum, totalColumns].Select(c => c.Value == null ? string.Empty : c.Value.ToString());
                        var enumerableCells             = row as string[] ?? row.ToArray();
                        var positionDataAccessComponent = new PositionDataProcessing(_ctx);

                        // Existing Position-Account implies Profile existence.
                        IQueryable <Asset> positionAccount = positionDataAccessComponent.GetPositionAssetByTickerAndAccount(enumerableCells.ElementAt(1).Trim(),
                                                                                                                            enumerableCells.ElementAt(0).Trim(),
                                                                                                                            id);
                        if (!positionAccount.Any())  // No Position-Account found.
                        {
                            IQueryable <Profile> profilePersisted = null;

                            // Are we processing a different ticker symbol?
                            if (lastTickerProcessed.Trim().ToUpper() != enumerableCells.ElementAt(1).Trim().ToUpper())
                            {
                                lastTickerProcessed = enumerableCells.ElementAt(1).Trim().ToUpper();

                                // Do we first have a standard web-derived Profile (via 3rd party) record in our database?
                                profilePersisted = profileDataAccessComponent.FetchDbProfile(enumerableCells.ElementAt(1).Trim(), "");
                                if (profilePersisted == null)
                                {
                                    // Do we secondly have a Customized Profile (via 3rd party) record in our database?
                                    // Check for lost _investorSvc reference.
                                    if (_investorSvc == null)
                                    {
                                        _investorSvc = new InvestorSvc(_ctx);
                                    }
                                    ;
                                    Investor currentInvestor = _investorSvc.GetById(id);
                                    profilePersisted = profileDataAccessComponent.FetchDbProfile(enumerableCells.ElementAt(1).Trim(), currentInvestor.LoginName);
                                }

                                if (profilePersisted != null)
                                {
                                    // Bypassing Profile creation for new Position.
                                    existingProfileId = profilePersisted.First().ProfileId;

                                    if (assetIdForPosition == string.Empty)
                                    {
                                        assetIdForPosition = newAssetId;
                                    }

                                    // Are we processing our first XLSX Position record?
                                    if (positionsToBeSaved == null)
                                    {
                                        positionsToBeSaved = InitializePositions(new List <Position>(), enumerableCells);
                                    }
                                    else
                                    {
                                        positionsToBeSaved = InitializePositions(positionsToBeSaved, enumerableCells);
                                    }

                                    // Error seeding collection.
                                    if (positionsToBeSaved == null)
                                    {
                                        return(null);
                                    }

                                    assetsToCreateList.Add(new AssetCreationVm
                                    {
                                        AssetId      = Guid.NewGuid().ToString(),
                                        AssetClassId = existingAssetClassId,
                                        InvestorId   = id,
                                        ProfileId    = existingProfileId,
                                        LastUpdate   = DateTime.Now,
                                        Positions    = positionsToBeSaved
                                    });
                                }
                                else
                                {
                                    // Obtain a new Profile via Tiingo API.
                                    var webProfileData = profileDataAccessComponent.BuildProfile(enumerableCells.ElementAt(1).Trim().ToUpper());
                                    if (webProfileData == null)
                                    {
                                        dataAccessComponent._exceptionTickers = enumerableCells.ElementAt(1).Trim().ToUpper();
                                        return(null);  // any necessary logging done via component.
                                    }
                                    else
                                    {
                                        // Dividend freq, months, & payDay all may be edited via 'Asset Profile'
                                        // functionality for any created *customized* Profile only. Any standard
                                        // Profile may NOT be edited this way, as this would impact many investors.
                                        Profile newProfile = new Profile
                                        {
                                            ProfileId     = webProfileData.ProfileId,
                                            DividendYield = webProfileData.DividendYield > 0
                                                ? webProfileData.DividendYield
                                                : 0,
                                            CreatedBy        = null,
                                            DividendRate     = webProfileData.DividendRate > 0 ? webProfileData.DividendRate : 0,
                                            ExDividendDate   = webProfileData.ExDividendDate ?? new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day),
                                            DividendFreq     = webProfileData.DividendFreq ?? "M",
                                            DividendMonths   = null,
                                            DividendPayDay   = 15,
                                            EarningsPerShare = webProfileData.EarningsPerShare > 0
                                                ? webProfileData.EarningsPerShare
                                                : 0,
                                            LastUpdate = DateTime.Now,
                                            PERatio    = webProfileData.PERatio > 0
                                                ? webProfileData.PERatio
                                                : 0,
                                            TickerDescription = webProfileData.TickerDescription.Trim(),
                                            TickerSymbol      = webProfileData.TickerSymbol.ToUpper().Trim(),
                                            UnitPrice         = webProfileData.UnitPrice
                                        };
                                        assetIdForPosition = newAssetId;
                                        assetsToCreateList.Add(new AssetCreationVm
                                        {
                                            AssetId      = Guid.NewGuid().ToString(),
                                            AssetClassId = existingAssetClassId,
                                            InvestorId   = id, //INVESTORID,
                                            ProfileId    = newProfile.ProfileId,
                                            LastUpdate   = DateTime.Now,
                                            Positions    = positionsToBeSaved == null
                                                ? InitializePositions(new List <Position>(), enumerableCells)
                                                : InitializePositions(positionsToBeSaved, enumerableCells),
                                            Profile = newProfile
                                        });
                                        foreach (var asset in assetsToCreateList)
                                        {
                                            if (asset.Positions.Count == 0)
                                            {
                                                Log.Error("Error creating new Position(s) for assetsToCreateList in ImportFileProcessing.ParsePortfolioSpreadsheetForAssetRecords().");
                                                return(null);
                                            }
                                        }
                                        ;
                                    }
                                }
                            }
                            else
                            {
                                // Asset header initialization & Profile check bypassed; processing SAME ticker - DIFFERENT account.
                                // Adding to existing AssetCreationVm.Positions.
                                var updatedPositions = InitializePositions(assetsToCreateList.Last().Positions.ToList(), enumerableCells);
                                assetsToCreateList.Last().Positions.Add(updatedPositions.Last());
                            }
                        }
                        else
                        {
                            // Attempted duplicate Position-Account insertion.
                            lastTickerProcessed = enumerableCells.ElementAt(1).Trim();
                        }
                    }   // end 'for'
                }       // end 'using'
            }
            catch (Exception ex)
            {
                if (ex.Message.Length > 0)
                {
                    Log.Error("Error found within ImportFileProcessing.ParsePortfolioSpreadsheetForAssetRecords(), due to {0}.", ex.Message);
                }
                else
                {
                    Log.Error("Error found within ImportFileProcessing.ParsePortfolioSpreadsheetForAssetRecords().");
                }

                return(null);
            }

            return(assetsToCreateList);
        }
Esempio n. 9
0
        public DataImportVm SaveAssets(DataImportVm importVmToSave, PIMS3Context _ctx, string id)
        {
            ImportFileProcessing busLogicComponent = new ImportFileProcessing(importVmToSave, _ctx, null);

            if (busLogicComponent.ValidateVm())
            {
                assetListingToSave = busLogicComponent.ParsePortfolioSpreadsheetForAssetRecords(importVmToSave.ImportFilePath.Trim(), this, id);

                if (assetListingToSave == null || assetListingToSave.Count() == 0)
                {
                    if (!string.IsNullOrEmpty(importVmToSave.ExceptionTickers))
                    {
                        importVmToSave.MiscMessage = "Error saving position(s) for " + importVmToSave.ExceptionTickers + ". Check position(s)";
                    }
                    else
                    {
                        importVmToSave.MiscMessage = BuildLogMessage("position(s)");
                    }

                    return(importVmToSave);
                }
                else
                {
                    List <Data.Entities.Profile>  profilesToSave  = new List <Data.Entities.Profile>();
                    List <Data.Entities.Asset>    assetsToSave    = new List <Data.Entities.Asset>();
                    List <Data.Entities.Position> positionsToSave = new List <Data.Entities.Position>();

                    for (int vmRecordIdx = 0; vmRecordIdx < assetListingToSave.Count(); vmRecordIdx++)
                    {
                        if (assetListingToSave.ElementAt(vmRecordIdx).Profile != null)
                        {
                            profilesToSave.Add(MapVmToEntities(assetListingToSave.ElementAt(vmRecordIdx).Profile) as Data.Entities.Profile);
                        }
                        else
                        {
                            profileDataAccessComponent = new ProfileDataProcessing(_ctx);
                        }

                        // "Asset" must first be initialized before referenced "Positions" can be added.
                        assetsToSave.Add(MapVmToEntities(assetListingToSave.ElementAt(vmRecordIdx)) as Data.Entities.Asset);

                        positionsToSave.Clear();
                        for (var position = 0; position < assetListingToSave.ElementAt(vmRecordIdx).Positions.Count(); position++)
                        {
                            positionsToSave.Add(MapVmToEntities(assetListingToSave.ElementAt(vmRecordIdx).Positions.ElementAt(position)) as Data.Entities.Position);
                            assetsToSave.ElementAt(vmRecordIdx).Positions.Add(positionsToSave.ElementAt(position));
                        }
                    }

                    // Persist to PIMS2Db.
                    try
                    {
                        // Omitting "using{}": DI handles disposing of ctx; *non-disposed ctx* needed for later
                        // call to profileDataAccessComponent.FetchDbProfileTicker().
                        if (profilesToSave.Count > 0)
                        {
                            _ctx.AddRange(profilesToSave);
                        }

                        _ctx.AddRange(assetsToSave);
                        recordsSaved = _ctx.SaveChanges();
                    }
                    catch (Exception ex)
                    {
                        Exception err = ex.InnerException;
                        Log.Error("Error persisting Profile(s)/Asset(s) to database within ImportFileDataProcessing.SaveAssets() due to {0}", err.Message);
                        return(null);
                    }
                }
            }

            return(HandleDbProcessingResults(importVmToSave, null, assetListingToSave));
        }