using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.IO; using System.Text; using NLog; using FileHelpers; using System.Data.Entity; using EnVisage.Code.BLL; using EnVisage.App_Start; using EnVisage.Models; namespace EnVisage.Code { [DelimitedRecord(",")] public class ActualsImportRow { public String ProjectNumber; public String WeekEndingDate; public String CostCenter; public String ExpenditureCategoryName; public String Quantity; public String Cost; } public class ImportActuals { EnVisageEntities _dbContext = new EnVisageEntities(); private Dictionary moDateColl; private Guid msScenarioOID; private Dictionary> maScenarioDetails = new Dictionary>(); //level 0 key=scenario.id. level 1 key = ExpenditureCategoryId + WeekEndingDate private long mlRecsProcessed; private long mlNumRecs; private long mlRecsBypassed; private byte mbPercentComplete; private List UpdatedSDs; public ImportActualsModel ProcessImport(ActualsImportRow[] ludtInFile, bool firstRowContainsHeaders, bool resetActuals, bool UOMhours, string userName, out string log) { var model = new ImportActualsModel(); UpdatedSDs = new List(); model.ResetActuals = resetActuals; model.Id = Guid.NewGuid(); var SDList = new List(); StringBuilder sbLog = new StringBuilder(); List gRates = new List(); Dictionary expenditureCategories = new Dictionary(); Dictionary costCenters = new Dictionary(); Dictionary actualsScenarioIds = new Dictionary(); Dictionary UOMValues = new Dictionary(); string lvHoldMissingPrjID = string.Empty; Guid lvHoldShowNoActuals = Guid.Empty; mlNumRecs = ludtInFile.LongLength; if (ludtInFile.Length < 1 || (firstRowContainsHeaders && ludtInFile.Length < 2)) { sbLog.AppendLine("- Import file does not seem to have enough records for import -- ending data import process."); log = sbLog.ToString(); model.Message = sbLog.ToString(); return model; } UOMValues = _dbContext.UOMs.ToDictionary(x => x.Id, x => x.UOMValue); //sort input array for better performance with current algorithm: ProjectNumber ASC, ExpCategory ASC, WKEndingDate ASC sbLog.AppendLine("- Sorting input data for better performance"); try { if (firstRowContainsHeaders) { List tmpFirstRow = ludtInFile.Take(1).ToList(); IOrderedEnumerable sortedColl = ludtInFile.Skip(1).OrderBy(r => r.ProjectNumber).ThenBy(r => r.ExpenditureCategoryName).ThenBy(r => DateTime.Parse(r.WeekEndingDate)); tmpFirstRow.AddRange(sortedColl); ludtInFile = tmpFirstRow.ToArray(); } else { ludtInFile = ludtInFile.OrderBy(r => r.ProjectNumber).ThenBy(r => r.ExpenditureCategoryName).ThenBy(r => DateTime.Parse(r.WeekEndingDate)).ToArray(); } } catch (Exception ex) { sbLog.AppendLine("- An error occurred while sorting data: " + ex.Message + " -- ending data import process."); log = sbLog.ToString(); model.Message = sbLog.ToString(); return model; } sbLog.AppendLine("- Retrieving all AWARDED Projects with non-empty unique Project Numbers from the database."); var allProjects = (from p in _dbContext.Projects join parentP in _dbContext.Projects on p.ParentProjectId equals parentP.Id into grProject from parentP in grProject.DefaultIfEmpty() where !p.HasChildren && ((!p.ParentProjectId.HasValue && !string.IsNullOrEmpty(p.ProjectNumber)) || (p.ParentProjectId.HasValue && !string.IsNullOrEmpty(parentP.ProjectNumber))) select new { Project = p, ParentProject = parentP }).ToList(); var projects = allProjects.Select(t => t.ParentProject ?? t.Project).ToList(); //var projectQuery = _dbContext.Projects.Where(p => p.Status.Name == "AWARDED" && p.ProjectNumber != ""); //foreach (Project p in projectQuery) //{ // if (projects.ContainsKey(p.ProjectNumber)) // { // sbLog.AppendLine("- There is more than one project with Project Number " + p.ProjectNumber + " in the system -- ending data import process."); // log = sbLog.ToString(); // return false; // } // projects.Add(p); //} if (projects.Count == 0) { sbLog.AppendLine("- 0 Projects retrieved -- ending data import process."); log = sbLog.ToString(); model.Message = sbLog.ToString(); return model; } else { sbLog.AppendLine("- " + projects.Count() + " Projects retrieved from the database."); } sbLog.AppendLine("- Retrieving all Expenditure Category data from the database."); var _expenditureCategories = _dbContext.ExpenditureCategory.AsNoTracking().ToList(); var _costCenters = _dbContext.CreditDepartments.AsNoTracking().ToList(); foreach (var exCat in _expenditureCategories) if (!expenditureCategories.Keys.Contains(exCat.Name)) expenditureCategories.Add(exCat.Name, exCat); // SA. ENV-756. ExpName -> ExpCatName foreach (var coCen in _costCenters) if (!costCenters.Keys.Contains(coCen.CreditNumber)) costCenters.Add(coCen.CreditNumber, coCen); if (expenditureCategories.Count() == 0) { sbLog.AppendLine("- 0 Expenditure Categories retrieved -- ending data import process."); log = sbLog.ToString(); model.Message = sbLog.ToString(); return model; } else { sbLog.AppendLine("- " + expenditureCategories.Count() + " Expenditure Categories retrieved from the database."); } var lsExpCatsForLRates = expenditureCategories.Values.Select(x=>x.Id).ToArray(); gRates = lsExpCatsForLRates.Length > 0 ? _dbContext.Rates.AsNoTracking().Where(t => t.Type == (short)RateModel.RateType.Global && lsExpCatsForLRates.Contains(t.ExpenditureCategoryId)) .OrderBy(t => t.ExpenditureCategoryId) .ThenBy(t => t.EndDate) .ToList() : _dbContext.Rates.AsNoTracking().Where(t => t.Type == (short)RateModel.RateType.Global) .OrderBy(t => t.ExpenditureCategoryId) .ThenBy(t => t.EndDate) .ToList(); for (int i = 0; i < ludtInFile.Length; i++ ) { if (i == 0 && firstRowContainsHeaders) continue; if (!expenditureCategories.ContainsKey(ludtInFile[i].ExpenditureCategoryName)) { //var Exp = new Expenditure(); //Exp.Id = Guid.NewGuid(); //Exp.Name = ludtInFile[i].ExpenditureCategoryName; //_dbContext.Expenditures.Add(Exp); //_dbContext.SaveChanges(); //var ExpCat = new ExpenditureCategory(); //ExpCat.Id = Guid.NewGuid(); //ExpCat.ExpenditureId = Exp.Id; //ExpCat.UOMId = null; sbLog.AppendLine("- Checking expenditure category existence failed - " + ludtInFile[i].ExpenditureCategoryName + " does not exist in the database -- ending data import process."); log = sbLog.ToString(); model.Message = sbLog.ToString(); return model; } } moDateColl = new Dictionary(); //bool firstWrite = true; // SA. Commented, because is unused Guid bucketScenarioId = Guid.Empty; Guid bucketExpenditureCatId = Guid.Empty; DateTime bucketWeekEndingDate = DateTime.MinValue; //decimal bucketQuantity = 0.0M; // SA. Commented, because is unused //decimal bucketCost = 0.0M; // SA. Commented, because is unused long arrayPointer = 0; Guid? currPrId = null; if (firstRowContainsHeaders) { mlRecsProcessed++; mbPercentComplete = Convert.ToByte(((decimal)mlRecsProcessed / (decimal)mlNumRecs) * (decimal)100); arrayPointer++; } sbLog.AppendLine("- Reading records from input data..."); msScenarioOID = Guid.Empty; for (long i = arrayPointer; i < mlNumRecs; i++) { ActualsImportRow row = ludtInFile[i]; DateTime rowWeekEndingDate = DateTime.MinValue; Guid rowProjectId = Guid.Empty; Guid[] rowProjectIds; Guid rowScenarioId = Guid.Empty; Guid rowExpenditureCatId = Guid.Empty; if (!DateTime.TryParse(row.WeekEndingDate, out rowWeekEndingDate)) { sbLog.AppendLine(" - ERROR: Line " + i + " has incorrectly formatted Week Ending Date. The import will be aborted"); log = sbLog.ToString(); model.Message = sbLog.ToString(); return model; } if (!CheckWeekForWorkStatus(rowWeekEndingDate)) //!tochange { sbLog.AppendLine(" - ERROR: Line " + i + " contains data for a non-work week period. The import will be aborted"); log = sbLog.ToString(); model.Message = sbLog.ToString(); return model; } mlRecsProcessed++; mbPercentComplete = Convert.ToByte(((decimal)mlRecsProcessed / (decimal)mlNumRecs) * (decimal)100); var currentProjects = projects.Where(x => x.ProjectNumber == row.ProjectNumber).ToArray(); if (projects.Select(x=>x.ProjectNumber).ToArray().Contains(row.ProjectNumber)) { rowProjectIds = projects.Where(x=>x.ProjectNumber == row.ProjectNumber).Select(x=>x.Id).Distinct().ToArray(); } else { if (lvHoldMissingPrjID != row.ProjectNumber) { lvHoldMissingPrjID = row.ProjectNumber; sbLog.AppendLine("- WARNING: Project with Project Number '" + lvHoldMissingPrjID + "' does not have a match in the database."); sbLog.AppendLine(" All subsequent import records with this Project Number will be bypassed."); sbLog.AppendLine(" This Project should be defined in Prevu. If it is defined, ensure the Project Number is correct."); } mlRecsBypassed++; continue; } foreach (var currProjectId in rowProjectIds) { bool first = true; currPrId = currProjectId; var currpr = projects.Where(x => x.Id == currProjectId).FirstOrDefault(); if (model.Projects.Where(x => x.ProjectId == currProjectId).Count() == 0) { var IAProject = new ImportActualsProject(); IAProject.ProjectId = currProjectId; IAProject.Checked = true; IAProject.ProjectName = currpr.Name; if (currpr.HasChildren) { first = true; var parts = _dbContext.Projects.Where(x => x.ParentProjectId == currProjectId).ToList(); foreach (var part in parts) { var currpart = new ImportActualsProjectPart(); currpart.PartName = part.Name; currpart.PartId = part.Id; currpart.Checked = true; if (first) { currpart.Distribution = 100; first = false; } else currpart.Distribution = 0; var scenario = _dbContext.Scenarios.Where(s => s.ParentId == part.Id && s.Type == (int)ScenarioType.Actuals).FirstOrDefault(); if (scenario == null || scenario.Id == Guid.Empty) { if (lvHoldShowNoActuals != part.Id) { lvHoldShowNoActuals = part.Id; sbLog.AppendLine("- No ACTUALS Scenario data located for Project part with Project Number '" + row.ProjectNumber + "' ...bypassing Project Part..."); } mlRecsBypassed++; continue; } currpart.ActualsScenarioId = scenario.Id; actualsScenarioIds.Add(part.Id, scenario.Id); IAProject.ProjectParts.Add(currpart); } } else { var scenario = _dbContext.Scenarios.Where(s => s.ParentId == currProjectId && s.Type == (int)ScenarioType.Actuals).FirstOrDefault(); if (scenario == null || scenario.Id == Guid.Empty) { if (lvHoldShowNoActuals != currProjectId) { lvHoldShowNoActuals = currProjectId; sbLog.AppendLine("- No ACTUALS Scenario data located for Project with Project Number '" + row.ProjectNumber + "' ...bypassing Project."); } mlRecsBypassed++; continue; } else { IAProject.ActualsScenarioId = scenario.Id; actualsScenarioIds.Add(currProjectId, scenario.Id); } } model.Projects.Add(IAProject); } //if (actualsScenarioIds.ContainsKey(currProjectId)) //{ // rowScenarioId = actualsScenarioIds[currProjectId]; //} //else //{ // var scenario = _dbContext.Scenarios.Where(s => s.ParentId == currProjectId && s.Type == (int)ScenarioType.Actuals).FirstOrDefault(); // if (scenario == null || scenario.Id == Guid.Empty) // { // if (lvHoldShowNoActuals != currProjectId) // { // lvHoldShowNoActuals = currProjectId; // sbLog.AppendLine("- No ACTUALS Scenario data located for Project with Project Number '" + row.ProjectNumber + "' ...bypassing Project."); // } // mlRecsBypassed++; // continue; // } // else { // } // rowScenarioId = scenario.Id; // actualsScenarioIds.Add(currProjectId, scenario.Id); //} if (string.IsNullOrEmpty(row.CostCenter) || !costCenters.ContainsKey(ludtInFile[i].CostCenter)) { rowExpenditureCatId = expenditureCategories[row.ExpenditureCategoryName].Id; } else { var currCC = costCenters[row.CostCenter]; var EC = currCC.ExpenditureCategory.Where(x => x.Name == ludtInFile[i].ExpenditureCategoryName).FirstOrDefault(); if (EC != null) rowExpenditureCatId = EC.Id; else rowExpenditureCatId = expenditureCategories[row.ExpenditureCategoryName].Id; } //uom, quantity and cost calculation decimal currCost = 0.0M; decimal currQuantity = 0.0M; if (!decimal.TryParse(row.Cost, out currCost) & !decimal.TryParse(row.Quantity, out currQuantity)) { mlRecsBypassed++; continue; } if (!decimal.TryParse(row.Cost, out currCost)) { if (!UOMhours) { currQuantity = currQuantity * UOMValues[_expenditureCategories.Where(x => x.Id == rowExpenditureCatId).FirstOrDefault().UOMId]; } var rate = gRates.Where(x => x.ExpenditureCategoryId == expenditureCategories[row.ExpenditureCategoryName].Id && x.StartDate <= rowWeekEndingDate && x.EndDate >= rowWeekEndingDate).FirstOrDefault(); if (rate != null) currCost = currQuantity * rate.Rate1; } else if (!decimal.TryParse(row.Quantity, out currQuantity)) { var rate = gRates.Where(x => x.ExpenditureCategoryId == expenditureCategories[row.ExpenditureCategoryName].Id && x.StartDate <= rowWeekEndingDate && x.EndDate >= rowWeekEndingDate).FirstOrDefault(); if (rate != null && rate.Rate1 > 0) currQuantity = currCost / rate.Rate1; } else { if (!UOMhours) { currQuantity = currQuantity * UOMValues[_expenditureCategories.Where(x => x.Id == rowExpenditureCatId).FirstOrDefault().UOMId]; } } if (currpr.HasChildren) { foreach (var part in model.Projects.Where(x => x.ProjectId == currProjectId).FirstOrDefault().ProjectParts) { StoreScDetailToCash(rowExpenditureCatId, rowWeekEndingDate, part.ActualsScenarioId, part.PartId, currQuantity, currCost, resetActuals, SDList); } } else { StoreScDetailToCash(rowExpenditureCatId, rowWeekEndingDate, actualsScenarioIds[currProjectId], currProjectId, currQuantity, currCost, resetActuals, SDList); } //if (rowScenarioId == bucketScenarioId && // rowExpenditureCatId == bucketExpenditureCatId && // rowWeekEndingDate == bucketWeekEndingDate) //{ // bucketQuantity += currQuantity; // bucketCost += currCost; //} //else //{ // if (firstWrite) // firstWrite = false; // else // { // StoreScDetailToCash(rowExpenditureCatId, bucketWeekEndingDate, bucketScenarioId, currProjectId, bucketQuantity, bucketCost, resetActuals, SDList); // } // bucketScenarioId = rowScenarioId; // bucketExpenditureCatId = rowExpenditureCatId; // bucketWeekEndingDate = rowWeekEndingDate; // bucketQuantity = currQuantity; // bucketCost = currCost; //} } } //if ((mlRecsProcessed - mlRecsBypassed > 0) && bucketScenarioId != Guid.Empty && bucketExpenditureCatId != Guid.Empty && currPrId.HasValue) //{ // StoreScDetailToCash(bucketExpenditureCatId, bucketWeekEndingDate, bucketScenarioId, currPrId.Value, bucketQuantity, bucketCost, resetActuals, SDList); //} var SessionId = Guid.NewGuid(); model.SessionId = SessionId; HttpContext.Current.Session[SessionId.ToString()] = SDList; sbLog.AppendLine(); sbLog.AppendLine("- Total import records - " + mlRecsProcessed); sbLog.AppendLine("- Total import records bypassed - " + mlRecsBypassed); sbLog.AppendLine("- Total import records processed - " + (mlRecsProcessed - mlRecsBypassed)); sbLog.AppendLine(); _dbContext.SaveChanges(); log = sbLog.ToString(); model.Message = sbLog.ToString(); model.ImportSuccessful = true; foreach (var pr in model.Projects) { if (!pr.ProjectParts.Any() && !actualsScenarioIds.ContainsKey(pr.ProjectId)) continue; //if (!pr.ProjectParts.Any()) {pr.ActualsScenarioId = actualsScenarioIds[pr.ProjectId]; if (SDList.Any(x => x.ParentId == pr.ActualsScenarioId)) { var startDate = SDList.Where(x => x.ParentId == pr.ActualsScenarioId).OrderBy(x => x.WeekEndingDate).FirstOrDefault().WeekEndingDate; var endDate = SDList.Where(x => x.ParentId == pr.ActualsScenarioId).OrderByDescending(x => x.WeekEndingDate).FirstOrDefault().WeekEndingDate; pr.StartDate = startDate.ToShortDateString(); pr.EndDate = endDate.ToShortDateString(); } else { foreach (var part in pr.ProjectParts) { var startDate = SDList.Where(x => x.ParentId == part.ActualsScenarioId).OrderBy(x => x.WeekEndingDate).FirstOrDefault(); if (startDate != null) { pr.StartDate = startDate.WeekEndingDate.ToShortDateString(); part.StartDate = startDate.WeekEndingDate.ToShortDateString(); } var endDate = SDList.Where(x => x.ParentId == part.ActualsScenarioId).OrderByDescending(x => x.WeekEndingDate).FirstOrDefault(); if (endDate != null) { pr.EndDate = endDate.WeekEndingDate.ToShortDateString(); part.EndDate = endDate.WeekEndingDate.ToShortDateString(); } } } } return model; } public bool CommitImport(ImportActualsModel model, string userName, out string log) { StringBuilder sbLog = new StringBuilder(); var ScenariosToModify = new List(); ScenariosToModify = model.Projects.Select(x => x.ActualsScenarioId).Distinct().ToList(); foreach (var proj in model.Projects) if (proj.ProjectParts.Count()>0) ScenariosToModify.AddRange(proj.ProjectParts.Select(x => x.ActualsScenarioId).Distinct().ToList()); //if (model.ResetActuals) // _dbContext.ScenarioDetail.RemoveRange(_dbContext.ScenarioDetail.Where(x => ScenariosToModify.Contains(x.ParentID.Value)).ToArray()); var SDList = HttpContext.Current.Session[model.SessionId.ToString()] as List ?? new List(); if (SDList.Count() == 0) { sbLog.AppendLine("Error loading imported data from session. Please retry importing actuals."); log = sbLog.ToString(); return false; } var allExpCats = _dbContext.ExpenditureCategory.AsNoTracking().ToDictionary(key => key.Id); foreach (var project in model.Projects) { if (project.Checked) { if (project.ProjectParts.Any())// && project.ProjectParts.Where(x => x.Checked == true).Count() > 0) { var parts = project.ProjectParts.Where(x => x.Checked == true).ToList(); foreach (var part in parts) { var details = SDList.Where(x => x.ParentId == part.ActualsScenarioId).ToList(); var partdetails = details.Where(x => x.WeekEndingDate >= DateTime.Parse(part.StartDate) && x.WeekEndingDate <= DateTime.Parse(part.EndDate)).ToList(); foreach (var pd in partdetails) { bool overlaps = parts.Count(x => DateTime.Parse(x.StartDate) <= pd.WeekEndingDate && DateTime.Parse(x.EndDate) >= pd.WeekEndingDate) > 1; if (overlaps) DoScDetailFlushToDB(pd.ExpenditureCategoryId, pd.WeekEndingDate, pd.ParentId, pd.Quantity*part.Distribution/100, pd.Cost*part.Distribution/100, model.ResetActuals); else DoScDetailFlushToDB(pd.ExpenditureCategoryId, pd.WeekEndingDate, pd.ParentId, pd.Quantity, pd.Cost, model.ResetActuals); } sbLog.AppendLine("- Updated Scenario with Id " + partdetails.FirstOrDefault().ParentId.ToString() + " to reflect accurate Start and End Dates."); var actualsScenarioId = part.ActualsScenarioId; Scenario scenario = _dbContext.Scenarios.FirstOrDefault(s => s.Id == actualsScenarioId); if (null != scenario) { var oldActualsDate = _dbContext.ScenarioDetail.Where(sd => sd.ParentID == scenario.Id).Min(sd => sd.WeekEndingDate); var newActualsDate = SDList.Where(sd => sd.ParentId == scenario.Id).Min(sd => sd.WeekEndingDate); if (oldActualsDate.HasValue && oldActualsDate < newActualsDate) scenario.StartDate = oldActualsDate.Value; else scenario.StartDate = newActualsDate; oldActualsDate = _dbContext.ScenarioDetail.Where(sd => sd.ParentID == scenario.Id).Max(sd => sd.WeekEndingDate); newActualsDate = SDList.Where(sd => sd.ParentId == scenario.Id).Max(sd => sd.WeekEndingDate); if (oldActualsDate.HasValue && oldActualsDate > newActualsDate) scenario.StartDate = oldActualsDate.Value; else scenario.EndDate = newActualsDate; var allActualRecords = maScenarioDetails[scenario.Id].Select(t => new ScenarioManager.ScenarioDetailsListItem { DetailCost = t.Value.Cost ?? 0, CategoryType = allExpCats.ContainsKey(t.Value.ExpenditureCategoryId ?? Guid.Empty) ? allExpCats[t.Value.ExpenditureCategoryId ?? Guid.Empty].Type.HasValue ? (ExpenditureCategoryModel.CategoryTypes)allExpCats[t.Value.ExpenditureCategoryId ?? Guid.Empty].Type.Value : ExpenditureCategoryModel.CategoryTypes.Undefined : ExpenditureCategoryModel.CategoryTypes.Undefined }).ToList(); var sm = new ScenarioManager(_dbContext); sm.SetBottomUpCosts(scenario, true, allActualRecords); scenario.LastUpdate = DateTime.Now; _dbContext.SaveChanges(); } } } else { //ContentLocker.AddLock("Scenario", scenario.Id.ToString(), userName); var details = SDList.Where(x => x.ParentId == project.ActualsScenarioId).ToList(); foreach (var ds in details) { DoScDetailFlushToDB(ds.ExpenditureCategoryId, ds.WeekEndingDate, ds.ParentId, ds.Quantity, ds.Cost, model.ResetActuals); } var scenarioId = project.ActualsScenarioId; Scenario scenario = _dbContext.Scenarios.FirstOrDefault(s => s.Id == scenarioId); if (null != scenario) { var oldActualsDate = _dbContext.ScenarioDetail.Where(sd => sd.ParentID == scenario.Id).Min(sd => sd.WeekEndingDate); var newActualsDate = SDList.Where(sd => sd.ParentId == scenario.Id).Min(sd => sd.WeekEndingDate); //TODO: check that we need to set start date as min end date. Maybe it should be equal to min(end date) - 6 days if (oldActualsDate.HasValue && oldActualsDate < newActualsDate) scenario.StartDate = oldActualsDate.Value; else scenario.StartDate = newActualsDate; oldActualsDate = _dbContext.ScenarioDetail.Where(sd => sd.ParentID == scenario.Id).Max(sd => sd.WeekEndingDate); newActualsDate = SDList.Where(sd => sd.ParentId == scenario.Id).Max(sd => sd.WeekEndingDate); if (oldActualsDate.HasValue && oldActualsDate > newActualsDate) scenario.EndDate = oldActualsDate.Value; else scenario.EndDate = newActualsDate; var allActualRecords = maScenarioDetails[scenario.Id].Select(t => new ScenarioManager.ScenarioDetailsListItem { DetailCost = t.Value.Cost ?? 0, CategoryType = allExpCats.ContainsKey(t.Value.ExpenditureCategoryId ?? Guid.Empty) ? allExpCats[t.Value.ExpenditureCategoryId ?? Guid.Empty].Type.HasValue ? (ExpenditureCategoryModel.CategoryTypes)allExpCats[t.Value.ExpenditureCategoryId ?? Guid.Empty].Type.Value : ExpenditureCategoryModel.CategoryTypes.Undefined : ExpenditureCategoryModel.CategoryTypes.Undefined }).ToList(); var sm = new ScenarioManager(_dbContext); sm.SetBottomUpCosts(scenario, true, allActualRecords); scenario.LastUpdate = DateTime.Now; _dbContext.SaveChanges(); } //ContentLocker.RemoveLock("Scenario", actualsScenarioIds[projectId].ToString(), userName); sbLog.AppendLine("- Updated Scenario with Id " + project.ActualsScenarioId.ToString() + " to reflect accurate Start and End Dates."); } } } sbLog.AppendLine("Updating scenario headers and actual buttom up direct costs."); sbLog.AppendLine(); sbLog.AppendLine("Data import is complete."); log = sbLog.ToString(); return true; } private void StoreScDetailToCash(Guid expenditureCategoryId, DateTime weekEndingDate, Guid scenarioId, Guid projectId, decimal quantity, decimal cost, bool resetActuals, List SDList) { var SDitem = new ImportActualsScenarioDetails(); var ExistingSD = SDList.Where(x => x.ExpenditureCategoryId == expenditureCategoryId && x.ParentId == scenarioId && x.WeekEndingDate == weekEndingDate).FirstOrDefault(); if (ExistingSD == null) { SDitem.Id = Guid.NewGuid(); SDitem.ParentId = scenarioId; SDitem.ProjectId = projectId; SDitem.ExpenditureCategoryId = expenditureCategoryId; SDitem.WeekEndingDate = weekEndingDate; SDitem.Cost = cost; SDitem.Quantity = quantity; SDList.Add(SDitem); UpdatedSDs.Add(SDitem.Id); return; } else { ExistingSD.Cost += cost; ExistingSD.Quantity += quantity; return; } } private void DoScDetailFlushToDB(Guid expenditureCategoryId, DateTime weekEndingDate, Guid scenarioId, decimal quantity, decimal cost, bool resetActuals) { ScenarioDetail detail = DetailUpdate(expenditureCategoryId, weekEndingDate, scenarioId); if (detail == null) { detail = new ScenarioDetail() { Id = Guid.NewGuid(), ParentID = scenarioId, ExpenditureCategoryId = expenditureCategoryId, WeekEndingDate = weekEndingDate, WeekOrdinal = 0, LastUpdate = DateTime.Now, Cost = cost, Quantity = quantity }; maScenarioDetails[scenarioId].Add(expenditureCategoryId.ToString() + weekEndingDate.ToString(), detail); _dbContext.ScenarioDetail.Add(detail); } else { if (!detail.Quantity.HasValue) detail.Quantity = 0; if (!detail.Cost.HasValue) detail.Cost = 0; if (resetActuals) { detail.Quantity = quantity; detail.Cost = cost; } else { detail.Quantity += quantity; detail.Cost += cost; } _dbContext.Entry(detail).State = EntityState.Modified; } } private ScenarioDetail DetailUpdate(Guid expenditureCategoryId, DateTime weekEndingDate, Guid scenarioId) { if(scenarioId == Guid.Empty) throw new ArgumentException("scenarioId"); if(scenarioId != msScenarioOID) { msScenarioOID = scenarioId; if (!maScenarioDetails.ContainsKey(msScenarioOID)) maScenarioDetails.Add(msScenarioOID, _dbContext.ScenarioDetail.Where(sd => sd.ParentID == msScenarioOID).OrderBy(sd => sd.ExpenditureCategoryId).ThenBy(sd => sd.WeekEndingDate). ToDictionary(sd => sd.ExpenditureCategoryId.ToString() + sd.WeekEndingDate.ToString())); } return maScenarioDetails[msScenarioOID].ContainsKey(expenditureCategoryId.ToString() + weekEndingDate.ToString()) ? maScenarioDetails[msScenarioOID][expenditureCategoryId.ToString() + weekEndingDate.ToString()] : null; } private bool CheckWeekForWorkStatus(DateTime psWeekEndDt) { if (moDateColl.Count == 0) { moDateColl = (from c in _dbContext.FiscalCalendars where c.Type == 0 && c.NonWorking == 1 select c).ToDictionary(c => c.EndDate); } return !moDateColl.ContainsKey(psWeekEndDt); } } }