using System; using System.Collections.Generic; using System.Linq; using System.Web.Mvc; using NHibernate; using NHibernate.Linq; using Sleis.Models; using Sleis.Infrastructure; using Sleis.Service; using Sleis.Utility; using Sleis.Validation; using Sleis.Validation.Attribute; using Sleis.ViewModels; using Sleis.Filter; using System.IO; using System.Web; using System.Web.Routing; using Sleis.Models.ErrorHandling; using Sleis.Validation.Spring; using Spring.Validation; using Sleis.CustomActionResult; using System.Text; namespace Sleis.Controllers { [HandleError] public class ProcessEmissionController : BaseController { public IProcessEmissionService ProcessEmissionService { get; set; } public IUnitProcessService UnitProcessService { get; set; } public IReportService ReportService { get; set; } public ObjectValidator ImportValidator { get; set; } public override void Init() { base.Init(); ArgumentValidationUtility.ThrowOnNull(ProcessEmissionService, "ProcessEmissionService"); ArgumentValidationUtility.ThrowOnNull(UnitProcessService, "UnitProcessService"); ArgumentValidationUtility.ThrowOnNull(ReportService, "ReportService"); } [Authorize, HttpGet] public ActionResult List(int reportId, int facilityId, int page=0) { SetSelectedFacility(facilityId); ProcessEmissionView processEmissionView = new ProcessEmissionView(); processEmissionView.Report = UserService.FacilityData.GetReport(facilityId, reportId); processEmissionView.NumberOfRecords = ProcessEmissionService.CountProcessEmissions(processEmissionView.Report.Id); //processEmissionView.List.List = ProcessEmissionService.GetProcessEmissionListItemsByReport(reportId); return View(processEmissionView); } [Authorize, HttpGet] public JsonResult GetEmissionFactors(string pollutantCode, string calculationMethodCode, string sccCode, string emissionFactorUomCode) { ListView results = new ListView(); results.List = ProcessEmissionService.GetEmissionFactors(pollutantCode, calculationMethodCode, sccCode, emissionFactorUomCode); return Json(results, JsonRequestBehavior.AllowGet); } [Authorize, HttpGet] public JsonResult CalculateControlEfficiency(int unitProcessId, string pollutantCode){ decimal result = ProcessEmissionService.CalculateControlEfficiency(unitProcessId, pollutantCode); return Json(result, JsonRequestBehavior.AllowGet); } [Authorize, HttpGet] public JsonResult CalculateEmissions(int unitProcessId, decimal? annualThroughput, string annualThroughputUom, string pollutantCode, string emissionCalculationMethod, decimal? emissionFactor, string emissionFactorUom, string annualThroughputTypeCode, decimal? percentAshContent, decimal? percentSulfurContent, decimal? actualSummerSeasonDays, decimal? percentSummerActual, decimal? percentOzoneSeasonActual, decimal? totalEmissions, string scc) { EmissionCalculation emission = new EmissionCalculation(unitProcessId, annualThroughput, annualThroughputUom, pollutantCode, emissionCalculationMethod, emissionFactor, emissionFactorUom, annualThroughputTypeCode, percentAshContent, percentSulfurContent, actualSummerSeasonDays, percentSummerActual, percentOzoneSeasonActual, totalEmissions, scc); emission = ProcessEmissionService.CalculateEmissions(emission); return Json(emission, JsonRequestBehavior.AllowGet); } [Authorize, HttpGet] public JsonResult Get(int reportId=0, int facilityId=0, int emissionUnitId=0, int unitProcessId = 0, int page=0) { ListView model = new ListView(); if (unitProcessId > 0) { //TODO: Hack since I didnt feel like writing a service method to fetch only one list item -- should be only one item model.List.AddRange(ProcessEmissionService.GetProcessEmissionListItems(reportId, emissionUnitId).Where(x=>x.UnitProcess.Id == unitProcessId)); } else { model.List = emissionUnitId > 0 ? ProcessEmissionService.GetProcessEmissionListItems(reportId, emissionUnitId) : ProcessEmissionService.GetProcessEmissionListItemsByReport(reportId, page, 0); } //model.List = model.List.OrderBy(x => x.UnitProcess.Identifier).ToList(); //return Json(model, JsonRequestBehavior.AllowGet); return new LargeJsonResult() { Data = model, MaxJsonLength = int.MaxValue, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; //MVC doesn't use webservices config setting for maxjsonlength } [HttpGet, Toggle] public ActionResult Details(int id, int reportId, int facilityId, int? unitProcessId) { ProcessEmissionDetailView dv = new ProcessEmissionDetailView(); dv.ProcessEmission = ProcessEmissionService.GetProcessEmission(id, unitProcessId ?? 0); dv.Report = FacilityService.GetFacilityEmissionReport(facilityId, reportId); SetSelectedFacility(facilityId); dv.Fields = PageService.GetPageFields(GetPageContext("ProcessEmission", "Details")); //dv.CustomFields = GetCustomFields(id, reportId, CustomFieldEntityType.ProcessEmission); return View(dv); } [Authorize, AppRoleValidation(AppUserRoleType.AgencyEditor,AppUserRoleType.FacilityEditor), HttpGet, Toggle] public ActionResult Edit(int id, int reportId, int facilityId, int? unitProcessId) { ProcessEmissionDetailView dv = new ProcessEmissionDetailView(); dv.ProcessEmission = ProcessEmissionService.GetProcessEmission(id, unitProcessId ?? 0); dv.Report = FacilityService.GetFacilityEmissionReport(facilityId, reportId); dv.Fields = PageService.GetPageFields(GetPageContext("ProcessEmission", "Edit")); //dv.CustomFields = GetCustomFields(id, reportId, CustomFieldEntityType.ProcessEmission); if (dv.ProcessEmission.Id == 0) { dv.ProcessEmission.IsCbi = false; //set default for UI dv.ProcessEmission.IsReported = true; //set default for UI } if (dv.ProcessEmission.Emissions == null || dv.ProcessEmission.Emissions.Count() == 0) { dv.ProcessEmission.Emissions = new List(); if (SessionUtility.CurrentUser.IsAgencyUser()) { dv.ProcessEmission.Emissions.Add(new AgencyEmission()); } else { dv.ProcessEmission.Emissions.Add(new PublicEmission()); } } return View(dv); } [Authorize,AppRoleValidation(AppUserRoleType.FacilityEditor,AppUserRoleType.AgencyEditor), HttpPost, Toggle] public ActionResult Edit(ProcessEmissionDetailView model, int reportId, int facilityId, bool? calculateSeasonalTotals, bool? calculateEmissions) { //make sure report is populated for validation purposes. model.Report = ReportService.GetReportFacility(facilityId, reportId).Report; foreach (Emission emission in model.ProcessEmission.Emissions) { //set Emission.ProcessEmission emission.ProcessEmission = model.ProcessEmission; } if (Validator.Validate(model, ModelState)) { if(calculateSeasonalTotals.HasValue && calculateSeasonalTotals == true) { ProcessEmissionService.CalculateSeasonalTotals(model.ProcessEmission); } //else if (calculateEmissions.HasValue && calculateEmissions == true) //{ // ProcessEmissionService.CalculateEmissions(model.ProcessEmission); //} else { //must be a save... model.ProcessEmission = ProcessEmissionService.SaveProcessEmission(model.ProcessEmission, model.CustomFields); TempData[Constants.GlobalMessageKey] = new SimpleMessage("The process emission was successfully updated."); //Need to update toggler ToggleInfo ti = GetTempData(Constants.ToggleInfo); if (ti != null) { ti.Records[ti.CurrentIndex].RecordId = model.ProcessEmission.Id; return RedirectToAction("Edit", new { id = model.ProcessEmission.Id, reportId = reportId, facilityId = facilityId, unitProcessId = model.ProcessEmission.UnitProcessId, toggleIndex = ti.CurrentIndex }); } //toggler info not setup. redirect back to list. return RedirectToAction("List", new { reportId = reportId, facilityId = facilityId }); } } //TempData[Constants.GlobalErrorMessageKey] = Constants.TabErrorMessage; TempData[Constants.GlobalMessageKey] = new SimpleMessage(ErrorOnSave, true); //model.CustomFields = GetCustomFields(model.ProcessEmission.Id, reportId, CustomFieldEntityType.ProcessEmission); model.Fields = PageService.GetPageFields(GetPageContext("ProcessEmission", "Edit")); model.Report = FacilityService.GetFacilityEmissionReport(facilityId, reportId); //reload return View(model); } public FileStreamResult DownloadTemplate(int reportId) { MemoryStream zipStream = new MemoryStream(); ProcessEmissionService.GenerateProcessEmissionsTemplatesZip(reportId, zipStream); zipStream.Position = 0;//reset position AgencyReport report = ReportService.ReportData.GetById(reportId); PublicFacilityModel facility = ReportService.FacilityData.GetReportFacility(reportId); return File(zipStream, "application/octet-stream", String.Format("{0}_{1}_{2}", report.Number, facility.FacilityIdentifier, "Emissions_Report_Template.zip")); } [Authorize, AppRoleValidation(AppUserRoleType.FacilityEditor), HttpGet] public ActionResult Import(int reportId, int facilityId) { AgencyReport report = ReportService.GetReportFacility(facilityId, reportId).Report; return View(report); } [Authorize, AppRoleValidation(AppUserRoleType.FacilityEditor), HttpPost] public ActionResult Import(int reportId, int facilityId, HttpPostedFileBase processesCsvFile, HttpPostedFileBase processEmissionsCsvFile) { ImportSummaryViewModel model = new ImportSummaryViewModel(); model.ReportId = reportId; model.FacilityId = facilityId; model.Report = ReportService.GetReportFacility(facilityId, reportId).Report; if (processesCsvFile != null) { try { CsvParserError errors = null; model.ProcessEmissions = ProcessEmissionService.ImportProcesses(processesCsvFile.InputStream, reportId, out errors); if (errors.HasErrors) model.AddErrors(errors); } catch (CsvParserError parserError) { //**BO - Shouldn't be happending anymore. Rather than throwing exception which results in null ProcessEMissions lisst for below, we wan't to capture errors, and move to import emissions. model.Errors.List.AddRange(parserError.ToRuleErrorList()); } } if (processEmissionsCsvFile != null) { try { model.Emissions = ProcessEmissionService.ImportEmissions(processEmissionsCsvFile.InputStream, reportId, model.ProcessEmissions); } catch (CsvParserError parserError) { model.Errors.List.AddRange(parserError.ToRuleErrorList()); } } if (model.Errors.Count == 0) { model.ProcessEmissions.ForEach(p => p.SetContext("~")); model.Emissions.ForEach(e => e.SetContext(String.Format("~Emission Unit: {0}, Process: {1},", e.EmissionUnitIdentifier, e.UnitProcessIdentifier))); //recalculate emissions model.Errors.List.AddRange(ProcessEmissionService.RecalculateEmissions(model.Emissions)); //run spring validation model.Errors.List.AddRange(ImportValidator.Validate(model)); } if (model.Errors.Count == 0) { model.NumOfProcessesImported = ProcessEmissionService.SaveProcesses(model.ProcessEmissions).Count; model.NumOfEmissionsImported = ProcessEmissionService.SaveProcessEmissions(model.Emissions).Count; } if(model.Errors.Count==0) { TempData[Constants.GlobalMessageKey] = new SimpleMessage( String.Format(@"Successfully imported {0} process records and {1} process emission records.", model.NumOfProcessesImported, model.NumOfEmissionsImported ) ); return RedirectToAction("Report", "Facility", new { id = reportId, facilityId = facilityId }); } foreach (RuleError rule in model.Errors.List) { int contextIndex = rule.Message.IndexOf("~"); if (contextIndex > -1) { rule.Context = rule.Message.Substring(contextIndex + 1).Trim(); rule.Message = rule.Message.Substring(0, contextIndex - 1).Trim(); } } if (model.Errors.Count > 0) CreateCsvFromErrors(model.Errors, model.Report.Number, AppUser.SelectedFacility.Facility.FacilityIdentifier); return View("ImportSummary", model); } //TODO: Refactor this logic so that it can be shared with similar logic on Validation controller public ActionResult GetValidationReportDocument(int facilityId, int reportId) { AgencyReport report = ReportService.GetAgencyReport(facilityId, reportId); string fileName = String.Format("{0}_{1}_{2}", report.Number, AppUser.SelectedFacility.Facility.FacilityIdentifier, "Import_Error_List.csv"); string filePath = Path.Combine(Path.GetTempPath(), fileName); return File(filePath, "text/csv", fileName); } private void CreateCsvFromErrors(ListView model, int reportYear, string facilityIdentifier) { if (model.Count > 0) { StringBuilder csv = new StringBuilder(); //header row csv.AppendLine(CsvUtility.CreateLine("Error", "Context")); for (int i = 0; i < model.Count; i++) { csv.AppendLine(CsvUtility.CreateLine(model.List[i].Message, model.List[i].Context)); } //File(Encoding.ASCII.GetBytes(csv.ToString()), "text/csv"); string filePath = Path.Combine(Path.GetTempPath(), String.Format("{0}_{1}_{2}", reportYear, facilityIdentifier, "Import_Error_List.csv")); System.IO.File.WriteAllText(filePath, csv.ToString()); } } } }