using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Saxonite.Net.Core.Web.Online.Models; using Saxonite.Net.Core.Web.Base.App; using Saxonite.Net.Core.Web.Base.Controllers; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Saxonite.Net.Standard.Base.Bus; using Sarand.Net.Standard.Base.App; using Sarand.Net.Standard.Base.Bus; using Sarand.Net.Standard.Base.Utils; using Sarand.Net.Standard.Base.Core; using Sarand.Net.Standard.Base.Dbas; using Saxonite.Net.Standard.Base.App; using static Saxonite.Net.Standard.Base.App.Sax.Config; using static Saxonite.Net.Standard.Base.Bus.SaxArticle; using Saxonite.Net.Standard.Base.Bus.Support; using static Saxonite.Net.Standard.Base.App.Sax; namespace Saxonite.Net.Core.Web.Online.Controllers { //======================================================================= // Online Support Controller - Feedback - Ajax actions. //======================================================================= partial class SupportController { //------------------------------------------------------------------- // Data definitions. private class UserReportResponseListData : AjaxResponse_Data.ItemData_Base { // Account Id only populated while account names are being queried, then nulled. public SysId UserAccountId { get; set; } public String UserDisplayName { get; set; } public String ReportTypeDesc { get; set; } public String ReportTitle { get; set; } public String RecordedOnDisp { get; set; } public bool? OwnReport { get; set; } } private class UserReportResponseItemData : UserReportResponseListData { public String ReportType { get; set; } public String Report { get; set; } public String RecordedOnForm { get; set; } } private void PopulateUserReportResponseListData(Model_Support model, SaxUserReport userReport, SaxUserAccount userAccount, UserReportResponseListData data) { data.Id = model.EncryptId(userReport.Id); data.UserDisplayName = userAccount.GetDisplayName(); data.ReportTypeDesc = Localiser.GetUserReportTypeCaption(userReport.ReportType); data.ReportTitle = userReport.Title; data.RecordedOnDisp = model.FormatDateForDisplay(userReport.RecordedOn); data.OwnReport = userAccount.Id.Equals(SessionUserAccountId) ? (bool?)true : null; } private void PopulateUserReportResponseItemData(Model_Support model, SaxUserReport userReport, SaxUserAccount userAccount, UserReportResponseItemData data) { PopulateUserReportResponseListData(model, userReport, userAccount, data); data.ReportType = UserReportTypeCodes.GetCodeForType(userReport.ReportType); data.Report = userReport.Report; data.RecordedOnForm = model.FormatDateForForm(userReport.RecordedOn); data.CreatedOnFmt = model.FormatDateForDisplay(userReport.CreateStamp.On); data.StatusCode = userReport.StatusCode; data.StatusDesc = userReport.StatusDesc; } //------------------------------------------------------------------- // Support - Get User Reports. //------------------------------------------------------------------- private class AjaxResponse_UserReportsData : AjaxResponse_Data { // Construction. public AjaxResponse_UserReportsData(SaxModel_Online model) : base(model) { } // Reference data. public List ReportTypes { get; } = new List(); // User Report list. public List Reports { get; } = new List(); } // Ajax request. [HttpPost] [Route("Support/Ajax/GetUserReports")] public IActionResult GetUserReports(Model_Support model) { String fn = GetType().Name + ".GetUserReports"; AjaxResponse_UserReportsData responseData = new AjaxResponse_UserReportsData(model); String messageTitle = Localiser["support.caption.user.reports"]; // Validate session and referrer. if (!ValidReferer) return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); RefreshModel(model); // Reference data - Report types. responseData.ReportTypes.Add(new AjaxResponse_Data.ItemCodeDesc()); List validReportTypes = new List(EnumUtil.GetValues()); foreach (TypeCodeDesc reportType in UserReportTypeCodes) { if (!validReportTypes.Contains((Sax.UserReportType)reportType.Type)) continue; responseData.ReportTypes.Add(new AjaxResponse_Data.ItemCodeDesc() { Code = reportType.Code, Desc = Localiser.GetUserReportTypeCaption((Sax.UserReportType)reportType.Type) }); } // Item filter. SaxUserReport.Params prmUserReport = new SaxUserReport.Params(); prmUserReport.UserAccountIdsIncluded.Add(SessionUserAccountId); prmUserReport.StatusCat = SaxUserReport.StatusCat.NotDeleted; model.Paging.ItemTotal = (ulong)SupportMgr.GetUserReportCount(prmUserReport); model.PopulatePagingTo(prmUserReport.ResultsPaging); // Item columns. ColumnDfn colId = SupportMgr.GetUserReportColumnDfn(SaxUserReport.Column.Id); ColumnDfn colUserAccountId = SupportMgr.GetUserReportColumnDfn(SaxUserReport.Column.UserAccountId); ColumnDfn colReportType = SupportMgr.GetUserReportColumnDfn(SaxUserReport.Column.ReportType); ColumnDfn colReportTitle = SupportMgr.GetUserReportColumnDfn(SaxUserReport.Column.Title); ColumnDfn colRecordedOn = SupportMgr.GetUserReportColumnDfn(SaxUserReport.Column.RecordedOn); ColumnDfn colStatus = SupportMgr.GetUserReportColumnDfn(SaxUserReport.Column.Status); List columns = new List() { colId, colUserAccountId, colReportType, colReportTitle,colRecordedOn, colStatus, }; // Sort columns. prmUserReport.SortColumns.Add(colRecordedOn); prmUserReport.SortColumns.Last().SortAscending = false; prmUserReport.SortColumns.Add(colId); prmUserReport.SortColumns.Last().SortAscending = false; // User account details must be queried separately - different database! HashSet userAccountIds = new HashSet(); // Query items. using (DbResultSet resultSet = SupportMgr.ExecuteUserReportQuery(columns, prmUserReport)) { while (resultSet != null && resultSet.HasRows && resultSet.NextRecord()) { NamedValue.Map values = resultSet.GetRecordValues(); SysId userAccountId = new SysId(values.GetLong(colUserAccountId.DataName)); userAccountIds.Add(userAccountId); Sax.UserReportType reportType = (Sax.UserReportType)values.GetLong(colReportType.DataName); UserReportResponseListData userReportData = new UserReportResponseListData() { Id = model.EncryptId(new SysId(values.GetLong(colId.DataName))), UserAccountId = userAccountId, ReportTypeDesc = Localiser.GetUserReportTypeCaption(reportType), ReportTitle = values.GetString(colReportTitle.DataName), RecordedOnDisp = model.FormatDateForDisplay(values.GetDate(colRecordedOn.DataName)), OwnReport = userAccountId.Equals(SessionUserAccountId) ? (bool?)true : null, StatusCode = values.GetString(colStatus.DataName), StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName)) }; responseData.Reports.Add(userReportData); } } if (model.Paging.IsPaged) model.Paging.ItemCount = (ushort)responseData.Reports.Count; // Query and populate User Account details. if (userAccountIds.Any()) { // User Account columns. ColumnDfn colUserAccount_Id = AccountMgr.GetUserAccountColumnDfn(SaxUserAccount.Column.Id); ColumnDfn colUserAccount_Title = AccountMgr.GetUserAccountColumnDfn(SaxUserAccount.Column.Title); ColumnDfn colUserAccount_FirstName = AccountMgr.GetUserAccountColumnDfn(SaxUserAccount.Column.FirstName); ColumnDfn colUserAccount_LastName = AccountMgr.GetUserAccountColumnDfn(SaxUserAccount.Column.LastName); List userAccountCols = new List() { colUserAccount_Id, colUserAccount_Title, colUserAccount_FirstName, colUserAccount_LastName }; // User Account filter. SaxUserAccount.Params prmUserAccount = new SaxUserAccount.Params(); prmUserAccount.IdsIncluded.AddRange(userAccountIds); prmUserAccount.StatusCat = SaxUserAccount.StatusCat.Any; // Query user accounts and populate properties to report list. using (DbResultSet resultSet = AccountMgr.ExecuteUserAccountQuery(userAccountCols, prmUserAccount)) { while (resultSet != null && resultSet.HasRows && resultSet.NextRecord()) { NamedValue.Map values = resultSet.GetRecordValues(); SysId userAccountId = new SysId(values.GetLong(colUserAccount_Id.DataName)); String title = values.GetString(colUserAccount_Title.DataName); String firstName = values.GetString(colUserAccount_FirstName.DataName); String lastName = values.GetString(colUserAccount_LastName.DataName); foreach (UserReportResponseListData userReportData in responseData.Reports.FindAll(item => item.UserAccountId.Equals(userAccountId))) { userReportData.UserDisplayName = SaxUserAccount.GetDisplayName(title, firstName, lastName); userReportData.UserAccountId = null; } } } // Clear any remaining User Account Ids. foreach (UserReportResponseListData userReportData in responseData.Reports.FindAll(item => item.UserAccountId != null)) userReportData.UserAccountId = null; } // Complete response. responseData.SetPaging(model); responseData.Success = true; return Json(responseData); } //------------------------------------------------------------------- // Get User Report ajax request. //------------------------------------------------------------------- private class AjaxResponse_UserReport : AjaxResponse_Data { // Construction. public AjaxResponse_UserReport(SaxModel_Online model) : base(model) { } // Sport details. public UserReportResponseItemData Report { get; } = new UserReportResponseItemData(); } //------------------------------------------------------------------- [HttpPost] [Route("Support/Ajax/GetUserReport")] public IActionResult Ajax_GetUserReport(Model_Support model) { String fn = GetType().Name + ".Ajax_GetUserReport"; String messageTitle = Localiser["support.caption.user.report"]; AjaxResponse_UserReport responseData = new AjaxResponse_UserReport(model); // Validate session and referrer. if (!ValidReferer) return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); RefreshModel(model); // Record disposable items as they are created so all can be disposed when needed. using (DisposableCollection disposableItems = new DisposableCollection()) { // Identify item. SysId userReportId = model.ExtractSysId(model.UserReport.Id); if (!SysId.IsValid(userReportId)) return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); // Retrieve item. SaxUserReport userReport = SupportMgr.GetUserReportById(userReportId); disposableItems.Add(userReport); if (userReport == null) { SaLogger.Warn(fn + " Failed to retrieve User Report for Id: '" + model.UserReport.Id + "'"); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"])); } // Retrieve user. SaxUserAccount userAccount = AccountMgr.GetUserAccountById(userReport.UserAccountId); disposableItems.Add(userAccount); if (userAccount == null) { SaLogger.Warn(fn + " Failed to retrieve User Account for Id: '" + userReport.UserAccountId + "'"); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"])); } // Construct response. PopulateUserReportResponseItemData(model, userReport, userAccount, responseData.Report); responseData.Success = true; } return Json(responseData); } //------------------------------------------------------------------- // Store User Report ajax request. //------------------------------------------------------------------- [HttpPost] [Route("Support/Ajax/StoreUserReport")] public IActionResult Ajax_StoreUserReport(Model_Support model) { String fn = GetType().Name + ".Ajax_StoreUserReport"; String messageTitle = Localiser["support.caption.user.report"]; AjaxResponse_UserReport responseData = new AjaxResponse_UserReport(model); // Validate session and referrer. if (!ValidReferer) return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); if (!SessionData_Online.User.Roles.Exists(item => item.Role == Sax.UserRole.SystemReviewer)) return Forbid(); RefreshModel(model); // Record disposable items as they are created so all can be disposed when needed. using (DisposableCollection disposableItems = new DisposableCollection()) { // Validate item properties. model.ValidateUserReportData(responseData); if (responseData.HasControlErrors()) return Json(responseData); // Validate User Report Id against 'Exists' flag. SysId userReportId = model.ExtractSysId(model.UserReport.Id); bool userReportExists = StringUtil.ToBool(model.UserReport.Exists); if (userReportExists && !SysId.IsValid(userReportId)) { SaLogger.Warn(fn + " Id not specified for existing User Report."); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); } if (!userReportExists && SysId.IsValid(userReportId)) { SaLogger.Warn(fn + " Id specified for new User Report: '" + model.UserReport.Id + "'"); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); } // Retrieve user. SysId userAccountId = SessionUserAccountId; SaxUserAccount userAccount = AccountMgr.GetUserAccountById(userAccountId); disposableItems.Add(userAccount); if (userAccount == null) { SaLogger.Warn(fn + " Failed to retrieve User Account for Id: '" + userAccountId + "'"); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"])); } // Retrieve existing item. SaxUserReport userReport = SupportMgr.GetUserReportById(userReportId); disposableItems.Add(userReport); if (userReport == null && SysId.IsValid(userReportId)) { SaLogger.Warn(fn + " Failed to retrieve User Report for Id: '" + model.UserReport.Id + "'"); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"])); } // Validate User Report properties. if (userReport != null) { if (!userReport.UserAccountId.Equals(userAccountId)) { SaLogger.Warn(fn + " Inconsistent User Account Id specified for User Report. Expected: " + userReport.UserAccountId + ". Found: " + userAccountId); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); } } // If User Report doesn't exist, create a new one. if (userReport == null) { userReport = SupportMgr.CreateUserReport(userAccountId); disposableItems.Add(userReport); userReport.RecordedOn = DateTime.Today; } // Populate item properties. if (model.UserReport.ReportType != null) userReport.ReportType = model.GetReportType(); if (model.UserReport.Title != null) userReport.Title = model.UserReport.Title; if (model.UserReport.Report != null) userReport.Report = model.UserReport.Report; // Store item. if (!SysId.IsValid(userReport.Id)) { if (!SupportMgr.InsertUserReport(userReport, DbUpdateInfo)) { SaLogger.Warn(fn + " Failed to insert user report: " + SupportMgr.ErrorStateMessage); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"])); } } else { if (!SupportMgr.UpdateUserReport(userReport, DbUpdateInfo)) { SaLogger.Warn(fn + " Failed to update user report [Id:" + SysId.ToString(userReport.Id) + "]: " + SupportMgr.ErrorStateMessage); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"])); } } // Construct response. PopulateUserReportResponseItemData(model, userReport, userAccount, responseData.Report); responseData.Success = true; } return Json(responseData); } //------------------------------------------------------------------- } //======================================================================= }