418 lines
20 KiB
C#
418 lines
20 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using Sarand.Net.Standard.Base.App;
|
|
using Sarand.Net.Standard.Base.Bus;
|
|
using Sarand.Net.Standard.Base.Core;
|
|
using Sarand.Net.Standard.Base.Dbas;
|
|
using Sarand.Net.Standard.Base.Utils;
|
|
using Saxonite.Net.Core.Web.Online.Models;
|
|
using Saxonite.Net.Standard.Base.App;
|
|
using Saxonite.Net.Standard.Base.Bus;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Saxonite.Net.Core.Web.Online.Controllers
|
|
{
|
|
//=======================================================================
|
|
// Online Organisation Controller - Opportunities - Ajax actions.
|
|
//=======================================================================
|
|
partial class OrganisationController
|
|
{
|
|
//-------------------------------------------------------------------
|
|
// Organisation Opportunity data.
|
|
private class OpportunityData_List : AjaxResponse_Data.ItemData_Base
|
|
{
|
|
public String TypeCode { get; set; }
|
|
public String TypeDesc { get; set; }
|
|
public String Position { get; set; }
|
|
public String Outline { get; set; }
|
|
public String RegionCaption { get; set; }
|
|
public String SportCaption { get; set; }
|
|
public String PublishedOnFmt { get; set; }
|
|
public String ExpiresOnFmt { get; set; }
|
|
}
|
|
private class OpportunityData_Detail : OpportunityData_List
|
|
{
|
|
public String RegionIdPrimary { get; set; }
|
|
public String SportIdPrimary { get; set; }
|
|
public String PublishedOn_YYYYMMDD { get; set; }
|
|
public String ExpiresOn_YYYYMMDD { get; set; }
|
|
}
|
|
private void PopulateOpportunityResponseData(Model_Organisation_Opportunities model, SaxOrganisationOpportunity opportunity, OpportunityData_List data)
|
|
{
|
|
data.Id = SysId.ToString(opportunity.Id);
|
|
data.TypeCode = OpportunityTypeCodes.GetCodeForType(opportunity.OpportunityType);
|
|
data.TypeDesc = Localiser.GetOpportunityTypeCaption(opportunity.OpportunityType);
|
|
data.Position = opportunity.Position;
|
|
data.Outline = opportunity.Outline;
|
|
data.RegionCaption = model.GetRegionCaption(opportunity.RegionIdPrimary);
|
|
data.SportCaption = model.GetSportCaption(opportunity.SportIdPrimary);
|
|
data.CreatedOnFmt = Localiser.FormatDate(opportunity.CreateStamp.On);
|
|
data.PublishedOnFmt = Localiser.FormatDate(opportunity.PublishedAt);
|
|
data.ExpiresOnFmt = Localiser.FormatDate(opportunity.ExpiresAt);
|
|
data.StatusCode = opportunity.StatusCode;
|
|
data.StatusDesc = opportunity.StatusDesc;
|
|
}
|
|
private void PopulateOpportunityResponseData(Model_Organisation_Opportunities model, SaxOrganisationOpportunity opportunity, OpportunityData_Detail data)
|
|
{
|
|
PopulateOpportunityResponseData(model, opportunity, data as OpportunityData_List);
|
|
data.RegionIdPrimary = SysId.ToString(opportunity.RegionIdPrimary);
|
|
data.SportIdPrimary = SysId.ToString(opportunity.SportIdPrimary);
|
|
data.PublishedOn_YYYYMMDD = DateUtil.Format(opportunity.PublishedAt, "yyyyMMdd");
|
|
data.ExpiresOn_YYYYMMDD = DateUtil.Format(opportunity.ExpiresAt, "yyyyMMdd");
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Get Opportunity List ajax request.
|
|
//-------------------------------------------------------------------
|
|
private class AjaxResponse_OpportunityList : AjaxResponse_Data
|
|
{
|
|
// Construction.
|
|
public AjaxResponse_OpportunityList(SaxModel_Online model) : base(model) { }
|
|
// Opportunity list.
|
|
public List<OpportunityData_List> Opportunities { get; } = new List<OpportunityData_List>();
|
|
// User profile.
|
|
public class UserData
|
|
{
|
|
public bool CanManage { get; set; }
|
|
}
|
|
public UserData User { get; } = new UserData();
|
|
// Organisation.
|
|
public class OrganisationData
|
|
{
|
|
public String Id { get; set; }
|
|
public String Name { get; set; }
|
|
public String SportId { get; set; }
|
|
public String SportName { get; set; }
|
|
public String RegionId { get; set; }
|
|
public String RegionName { get; set; }
|
|
}
|
|
public OrganisationData Organisation { get; } = new OrganisationData();
|
|
// Reference data.
|
|
public List<CodeDesc> OpportunityTypes { get; } = new List<CodeDesc>();
|
|
}
|
|
//-------------------------------------------------------------------
|
|
[HttpPost]
|
|
[Route("Organisation/Ajax/GetOpportunityList")]
|
|
[Route("Organisation/Ajax/GetOpportunities")]
|
|
public IActionResult Ajax_GetOpportunityList(Model_Organisation_Opportunities model)
|
|
{
|
|
String fn = GetType().Name + ".Ajax_GetOpportunityList";
|
|
String messageTitle = Localiser["organisation.caption.opportunities"];
|
|
AjaxResponse_OpportunityList responseData = new AjaxResponse_OpportunityList(model);
|
|
|
|
// Validate session and referrer.
|
|
if (!ValidReferer) return Forbid();
|
|
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
|
RefreshModel(model);
|
|
SysId userAccountId = SessionData.User.UserAccountId;
|
|
|
|
// Record disposable items as they are created so all can be disposed when needed.
|
|
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
|
|
{
|
|
|
|
// Organisation.
|
|
SysId organisationId = model.ExtractSysId(model.Filter.OrganisationId);
|
|
SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationId);
|
|
disposableItems.Add(organisation);
|
|
if (organisation == null || !organisation.IsStatusActive)
|
|
{
|
|
SaLogger.Warn(fn + " " + (organisation == null ? "Invalid" : "Inactive") + " organisation for Opportunity list. OrganisationId: '" + model.Filter.OrganisationId + "'");
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
|
}
|
|
|
|
if (organisation != null)
|
|
{
|
|
// Store filter data.
|
|
SessionData_Online.Filter.SetMemberOrganisation(organisation);
|
|
|
|
// Reference data - opportunity types.
|
|
foreach (TypeCodeDesc opportunityType in OpportunityTypeCodes)
|
|
responseData.OpportunityTypes.Add(opportunityType.Code, Localiser.GetOpportunityTypeCaption((Sax.OpportunityType)opportunityType.Type));
|
|
|
|
// User organisation.
|
|
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
|
|
prmUserOrganisation.UserAccountIdsIncluded.Add(userAccountId);
|
|
prmUserOrganisation.OrganisationIdsIncluded.Add(organisationId);
|
|
prmUserOrganisation.UserAccountStatusCat = SaxUserAccount.StatusCat.ActiveOnly;
|
|
prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.ActiveOnly;
|
|
SaxUserOrganisation userOrganisation = AccountMgr.GetUserOrganisation(prmUserOrganisation);
|
|
disposableItems.Add(userOrganisation);
|
|
if (userOrganisation == null)
|
|
{
|
|
SaLogger.Warn(fn + " Invalid/inactive user organisation for Opportunity list. UserAccountId: " + SysId.ToString(userAccountId) + ". OrganisationId: " + model.Filter.OrganisationId + ".");
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
|
}
|
|
|
|
// Organisation.
|
|
responseData.Organisation.Id = SysId.ToString(organisation.Id);
|
|
responseData.Organisation.Name = organisation.Name;
|
|
responseData.Organisation.SportId = SysId.ToString(organisation.SportIdPrimary);
|
|
responseData.Organisation.SportName = model.GetSportCaption(organisation.SportIdPrimary);
|
|
responseData.Organisation.RegionId = SysId.ToString(organisation.RegionIdPrimary);
|
|
responseData.Organisation.RegionName = model.GetRegionCaption(organisation.RegionIdPrimary);
|
|
|
|
// User details.
|
|
responseData.User.CanManage = userOrganisation?.HasOrganisationRole(Sax.OrganisationRole.OpportunityAdmin) ?? false;
|
|
|
|
// Item filter.
|
|
SaxOrganisationOpportunity.Params prmOpportunity = new SaxOrganisationOpportunity.Params();
|
|
prmOpportunity.UserAccountIdsIncluded.Add(userAccountId);
|
|
prmOpportunity.OrganisationIdsIncluded.Add(organisationId);
|
|
prmOpportunity.OpportunityFilter = model.Filter.Opportunity;
|
|
prmOpportunity.StatusCat = SaxOrganisationOpportunity.StatusCat.NotDeleted;
|
|
model.Paging.ItemTotal = (ulong)ActivityMgr.GetOrganisationOpportunityCount(prmOpportunity);
|
|
model.PopulatePagingTo(prmOpportunity.ResultsPaging);
|
|
|
|
// Item columns.
|
|
ColumnDfn colId = ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Id);
|
|
ColumnDfn colOpportunityTypeCode = ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.OpportunityTypeCode);
|
|
ColumnDfn colPosition = ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Position);
|
|
ColumnDfn colOutline = ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Outline);
|
|
ColumnDfn colRegionId = ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.RegionIdPrimary);
|
|
ColumnDfn colRegionName = ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Region_Name);
|
|
ColumnDfn colSportId = ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.SportIdPrimary);
|
|
ColumnDfn colSportName = ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Sport_Name);
|
|
ColumnDfn colPublishedOn = ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.PublishedAt_Date);
|
|
ColumnDfn colExpiresOn = ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.ExpiresAt_Date);
|
|
ColumnDfn colStatus = ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Status);
|
|
ColumnDfn colCreatedOn = ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.CreateOn_Date);
|
|
List<ColumnDfn> columns = new List<ColumnDfn>()
|
|
{
|
|
colId, colOpportunityTypeCode, colPosition, colOutline,
|
|
colRegionId, colRegionName, colSportId, colSportName,
|
|
colPublishedOn, colExpiresOn,
|
|
colStatus, colCreatedOn
|
|
};
|
|
|
|
// Sort columns.
|
|
colCreatedOn.SortAscending = false;
|
|
prmOpportunity.SortColumns.Add(colCreatedOn);
|
|
|
|
// Query items.
|
|
using (DbResultSet resultSet = ActivityMgr.ExecuteOrganisationOpportunityQuery(columns, prmOpportunity))
|
|
{
|
|
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
|
{
|
|
NamedValue.Map values = resultSet.GetRecordValues();
|
|
OpportunityData_List opportunityData = new OpportunityData_List()
|
|
{
|
|
Id = values.GetLong(colId.DataName).ToString(),
|
|
TypeCode = values.GetString(colOpportunityTypeCode.DataName),
|
|
TypeDesc = Localiser.GetOpportunityTypeCaption((Sax.OpportunityType)OpportunityTypeCodes.GetTypeForCode(values.GetString(colOpportunityTypeCode.DataName))),
|
|
Position = values.GetString(colPosition.DataName),
|
|
Outline = values.GetString(colOutline.DataName),
|
|
RegionCaption = model.GetRegionCaption(values.GetString(colRegionId.DataName).ToSysId()),
|
|
SportCaption = model.GetSportCaption(values.GetString(colSportId.DataName).ToSysId()),
|
|
CreatedOnFmt = Localiser.FormatDate(values.GetDateTime(colCreatedOn.DataName)),
|
|
PublishedOnFmt = Localiser.FormatDate(values.GetDateTime(colPublishedOn.DataName)),
|
|
ExpiresOnFmt = Localiser.FormatDate(values.GetDateTime(colExpiresOn.DataName)),
|
|
StatusCode = values.GetString(colStatus.DataName),
|
|
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))
|
|
};
|
|
responseData.Opportunities.Add(opportunityData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (model.Paging.IsPaged)
|
|
model.Paging.ItemCount = (ushort)responseData.Opportunities.Count;
|
|
|
|
// Complete response.
|
|
responseData.SetPaging(model);
|
|
responseData.Success = true;
|
|
return Json(responseData);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Get Opportunity ajax request.
|
|
//-------------------------------------------------------------------
|
|
private class AjaxResponse_Opportunity : AjaxResponse_Data
|
|
{
|
|
// Construction.
|
|
public AjaxResponse_Opportunity(SaxModel_Online model) : base(model) { }
|
|
// Opportunity details.
|
|
public OpportunityData_Detail Opportunity { get; } = new OpportunityData_Detail();
|
|
}
|
|
//-------------------------------------------------------------------
|
|
[HttpPost]
|
|
[Route("Organisation/Ajax/GetOpportunity")]
|
|
public IActionResult Ajax_GetOpportunity(Model_Organisation_Opportunities model)
|
|
{
|
|
String fn = GetType().Name + ".Ajax_GetOpportunity";
|
|
String messageTitle = Localiser["organisation.caption.opportunity"];
|
|
AjaxResponse_Opportunity responseData = new AjaxResponse_Opportunity(model);
|
|
|
|
// Validate session and referrer.
|
|
if (!ValidReferer) return Forbid();
|
|
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
|
RefreshModel(model);
|
|
|
|
// Identify item.
|
|
SysId opportunityId = model.ExtractSysId(model.OpportunityId);
|
|
if (!SysId.IsValid(opportunityId))
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
|
|
|
// Retrieve item.
|
|
using (SaxOrganisationOpportunity opportunity = ActivityMgr.GetOrganisationOpportunityById(opportunityId))
|
|
{
|
|
if (opportunity == null)
|
|
{
|
|
SaLogger.Warn(fn + " Failed to retrieve Organisation Opportunity for Id: '" + model.OpportunityId + "'");
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
|
}
|
|
|
|
// Validate organisation.
|
|
using (SaxOrganisation organisation = AccountMgr.GetOrganisationById(opportunity.OrganisationId))
|
|
{
|
|
if (organisation == null || !organisation.IsStatusActive)
|
|
{
|
|
SaLogger.Warn(fn + " " + (organisation == null ? "Invalid" : "Inactive") + " organisation for Opportunity. OrganisationId: '" + opportunity.OrganisationId + "'");
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
|
}
|
|
|
|
// Make a note of the selected Organisation.
|
|
SessionData_Online.Filter.SetMemberOrganisation(organisation);
|
|
|
|
// Construct response.
|
|
PopulateOpportunityResponseData(model, opportunity, responseData.Opportunity);
|
|
}
|
|
}
|
|
|
|
// Complete response.
|
|
responseData.Success = true;
|
|
return Json(responseData);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Store Opportunity ajax request.
|
|
//-------------------------------------------------------------------
|
|
[HttpPost]
|
|
[Route("Organisation/Ajax/StoreOpportunity")]
|
|
public IActionResult Ajax_StoreOpportunity(Model_Organisation_Opportunities model)
|
|
{
|
|
String fn = GetType().Name + ".Ajax_StoreOpportunity";
|
|
String messageTitle = Localiser["organisation.caption.opportunity"];
|
|
AjaxResponse_Opportunity responseData = new AjaxResponse_Opportunity(model);
|
|
|
|
// Validate session and referrer.
|
|
if (!ValidReferer) return Forbid();
|
|
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
|
RefreshModel(model);
|
|
|
|
// Validate item properties.
|
|
model.ValidateOpportunityData(responseData);
|
|
if (responseData.HasControlErrors())
|
|
return Json(responseData);
|
|
|
|
// Validate Opportunity against Id against 'Exists' flag.
|
|
SysId opportunityId = model.ExtractSysId(model.OpportunityId);
|
|
bool opportunityExists = StringUtil.ToBool(model.OpportunityExists);
|
|
if (opportunityExists && !SysId.IsValid(opportunityId))
|
|
{
|
|
SaLogger.Warn(fn + " Id not specified for existing Opportunity.");
|
|
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
|
|
}
|
|
if (!opportunityExists && SysId.IsValid(opportunityId))
|
|
{
|
|
SaLogger.Warn(fn + " Id specified for new Opportunity: '" + model.OpportunityId + "'");
|
|
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
|
|
}
|
|
|
|
// Record disposable items as they are created so all can be disposed when needed.
|
|
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
|
|
{
|
|
|
|
// Retrieve existing item.
|
|
SaxOrganisationOpportunity opportunity = ActivityMgr.GetOrganisationOpportunityById(opportunityId);
|
|
disposableItems.Add(opportunity);
|
|
if (opportunity == null && SysId.IsValid(opportunityId))
|
|
{
|
|
SaLogger.Warn(fn + " Failed to retrieve opportunity for Id: '" + model.OpportunityId + "'");
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
|
}
|
|
|
|
// Validate the Organisation.
|
|
SysId organisationId = model.ExtractSysId(model.OpportunityOrganisationId);
|
|
if (!SysId.IsValid(organisationId))
|
|
{
|
|
SaLogger.Warn(fn + " Organisation Id not specified for Opportunity.");
|
|
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
|
|
}
|
|
SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationId);
|
|
disposableItems.Add(organisation);
|
|
if (organisation == null || !organisation.IsStatusActive)
|
|
{
|
|
SaLogger.Warn(fn + " " + (organisation == null ? "Invalid" : "Inactive") + " organisation for Opportunity. OrganisationId: '" + model.OpportunityOrganisationId + "'");
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
|
}
|
|
if (opportunity != null && !opportunity.OrganisationId.Equals(organisationId))
|
|
{
|
|
SaLogger.Warn(fn + " Inconsistent Organisation Id specified for Opportunity. Expected: " + opportunity.OrganisationId + ". Found: " + organisationId);
|
|
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
|
|
}
|
|
|
|
// Ensure that the user has the correct role to update Opportunities for this organisation.
|
|
if (!AccountMgr.UserHasOrganisationRole(SessionData.User.UserAccountId, organisationId, Sax.OrganisationRole.OpportunityAdmin))
|
|
{
|
|
SaLogger.Warn(fn + " User doesn't have 'Opportunity Admin' role for Organisation Id: " + organisationId);
|
|
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
|
|
}
|
|
|
|
// Create new item if required.
|
|
if (opportunity == null)
|
|
{
|
|
opportunity = ActivityMgr.CreateOrganisationOpportunity(organisationId);
|
|
disposableItems.Add(opportunity);
|
|
}
|
|
|
|
// Populate item properties.
|
|
if (model.OpportunityRegionId != null)
|
|
opportunity.RegionIdPrimary = model.ExtractSysId(model.OpportunityRegionId);
|
|
if (model.OpportunitySportId != null)
|
|
opportunity.SportIdPrimary = model.ExtractSysId(model.OpportunitySportId);
|
|
if (model.OpportunityTypeCode != null)
|
|
opportunity.OpportunityType = (Sax.OpportunityType)OpportunityTypeCodes.GetTypeForCode(model.OpportunityTypeCode);
|
|
if (model.OpportunityPosition != null)
|
|
opportunity.Position = model.OpportunityPosition;
|
|
if (model.OpportunityOutline != null)
|
|
opportunity.Outline = model.OpportunityOutline;
|
|
if (model.OpportunityStatusCode != null)
|
|
opportunity.Status = model.OpportunityStatus;
|
|
|
|
// Store item.
|
|
if (!SysId.IsValid(opportunity.Id))
|
|
{
|
|
if (!ActivityMgr.InsertOrganisationOpportunity(opportunity, DbUpdateInfo))
|
|
{
|
|
SaLogger.Warn(fn + " Failed to insert opportunity: " + ActivityMgr.ErrorStateMessage);
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!ActivityMgr.UpdateOrganisationOpportunity(opportunity, DbUpdateInfo))
|
|
{
|
|
SaLogger.Warn(fn + " Failed to update opportunity [Id:" + SysId.ToString(opportunity.Id) + "]: " + ActivityMgr.ErrorStateMessage);
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
|
|
}
|
|
}
|
|
|
|
// Store Opportunity Activity Index data.
|
|
ActivityConsole.StoreActivityIndex(opportunity, DbUpdateInfo);
|
|
|
|
// Construct response.
|
|
PopulateOpportunityResponseData(model, opportunity, responseData.Opportunity);
|
|
}
|
|
|
|
// Complete response.
|
|
responseData.Success = true;
|
|
return Json(responseData);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
//=======================================================================
|
|
}
|