public bool SavePositionsWithOverdueIncome(List <DelinquentIncome> delinquentPositions) { _ctx.AddRange(delinquentPositions); recordsSaved = _ctx.SaveChanges(); return(recordsSaved > 0 ? true : false); }
public DataImportVm SaveRevenue(DataImportVm importVmToUpdate, PIMS3Context _ctx, string investorId) { // Processing includes: // 1. persisting revenue, // 2. persisting revenue delinquencies, and // 3. updating Positions ("PymtDue") where applicable. ImportFileProcessing busLayerComponent = new ImportFileProcessing(importVmToUpdate, _ctx, null); IEnumerable <Income> revenueListingToSave; PositionDataProcessing positionDataAccessComponent = new PositionDataProcessing(_ctx); if (busLayerComponent.ValidateVm()) { revenueListingToSave = busLayerComponent.ParseRevenueSpreadsheetForIncomeRecords(importVmToUpdate.ImportFilePath.Trim(), this, investorId); if (revenueListingToSave == null || revenueListingToSave.Count() == 0) { if (!string.IsNullOrEmpty(importVmToUpdate.ExceptionTickers)) { importVmToUpdate.MiscMessage = "Error saving revenue for " + importVmToUpdate.ExceptionTickers + ". Check position(s)."; } else { importVmToUpdate.MiscMessage = BuildLogMessage("revenue"); } return(importVmToUpdate); } else { // Persist to 'Income'. Deferring use of using{}: ctx scope needed. _ctx.AddRange(revenueListingToSave); recordsSaved = _ctx.SaveChanges(); } if (recordsSaved > 0) { totalAmtSaved = 0M; foreach (var record in revenueListingToSave) { totalAmtSaved += record.AmountRecvd; } // Returned values to UI. importVmToUpdate.AmountSaved = totalAmtSaved; importVmToUpdate.RecordsSaved = recordsSaved; // Update Positions. positionDataAccessComponent.UpdatePositionPymtDueFlags(ExtractPositionIdsForPymtDueProcessing(revenueListingToSave), true); /* === Month-end delinquent revenue processing === */ // If at month end/beginning, we'll query Positions for any now delinquent income receivables via "PymtDue" flag. // Any unpaid income receivables, those not marked as received via 'Income due', will STILL have their 'PymtDue' flag set as // True, and hence will now be considered a delinquent Position, resulting in persistence to 'DelinquentIncome' table. // Delinquent position searches may ONLY be performed during month-end xLSX processing, as income receipts are still being // accepted during the month via 'Income due'. During 'Income due' payments, flags are set accordingly: [PymtDue : True -> False]. // Any delinquent Positions will automatically be added to the 'Income due' collection that is broadcast via the UI schedule, // for necessary action. if (DateTime.Now.Day <= 3 && DateTime.Now.DayOfWeek.ToString() != "Saturday" && DateTime.Now.DayOfWeek.ToString() != "Sunday") { //PositionDataProcessing positionDataAccessComponent = new PositionDataProcessing(_ctx); IQueryable <dynamic> filteredPositionAssetJoinData = positionDataAccessComponent.GetCandidateDelinquentPositions(investorId); IList <DelinquentIncome> pastDueListing = new List <DelinquentIncome>(); string delinquentMonth = DateTime.Now.AddMonths(-1).Month.ToString().Trim(); int matchingPositionDelinquencyCount = 0; IList <DelinquentIncome> existingDelinqencies = positionDataAccessComponent.GetSavedDelinquentRecords(investorId, ""); int duplicateDelinquencyCount = 0; foreach (dynamic joinData in filteredPositionAssetJoinData) { // 'DelinquentIncome' PKs: InvestorId, MonthDue, PositionId // Do we have a match based on PositionId & InvestorId ? If so, Position is eligible for omitting setting 'PymtDue' to True. matchingPositionDelinquencyCount = existingDelinqencies.Where(d => d.PositionId == joinData.PositionId && d.InvestorId == joinData.InvestorId).Count(); if (matchingPositionDelinquencyCount >= 1) { // Do we have a duplicate entry ? duplicateDelinquencyCount = existingDelinqencies.Where(d => d.PositionId == joinData.PositionId && d.InvestorId == joinData.InvestorId && d.MonthDue == delinquentMonth).Count(); } if (joinData.DividendFreq == "M") { if (matchingPositionDelinquencyCount > 0 && duplicateDelinquencyCount == 0) { pastDueListing.Add(InitializeDelinquentIncome(joinData)); } else { continue; } } else { string[] divMonths = joinData.DividendMonths.Split(','); for (var i = 0; i < divMonths.Length; i++) { if (divMonths[i].Trim() == delinquentMonth) { if (matchingPositionDelinquencyCount > 0 && duplicateDelinquencyCount == 0) { pastDueListing.Add(InitializeDelinquentIncome(joinData)); } else { continue; } } } } matchingPositionDelinquencyCount = 0; } // Persist to 'DelinquentIncome' as needed. if (pastDueListing.Any()) { bool pastDueSaved = positionDataAccessComponent.SaveDelinquencies(pastDueListing.ToList()); if (pastDueSaved) { importVmToUpdate.MiscMessage = "Found & stored " + pastDueListing.Count() + " Position(s) with delinquent revenue."; Log.Information("Saved {0} delinquent position(s) to 'DelinquentIncome' via ImportFileDataProcessing.SaveRevenue()", pastDueListing.Count()); } } // Finally, update PymtDue flags on received XLSX positions. positionDataAccessComponent.UpdatePositionPymtDueFlags(ExtractPositionIdsForPymtDueProcessing(revenueListingToSave), true); } } _ctx.Dispose(); } // Missing amount & record count reflects error condition. return(importVmToUpdate); }
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)); }