304 lines
15 KiB
C#
304 lines
15 KiB
C#
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 Sarand.Net.Standard.Dbas.Data;
|
|
using Saxonite.Base.App;
|
|
using Saxonite.Net.Standard.Base.App;
|
|
using Saxonite.Net.Standard.Base.Bus;
|
|
using Saxonite.Net.Standard.Base.Consoles;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Saxonite.Net.Core.Web.Base.Consoles
|
|
{
|
|
//=======================================================================
|
|
public abstract class SaxActivityConsole_Web : SaxActivityConsole
|
|
{
|
|
//-------------------------------------------------------------------
|
|
// Data members.
|
|
private readonly SaxInternals internals;
|
|
private readonly String alias_ActivityIndex = "ActIdx";
|
|
protected class IndexStatsData
|
|
{
|
|
public int EntriesInserted { get; set; }
|
|
public int EntriesUpdated { get; set; }
|
|
public int EntriesDeleted { get; set; }
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Protected construction.
|
|
protected SaxActivityConsole_Web(SaxSessionContext sessionContext) :
|
|
base(sessionContext)
|
|
{
|
|
internals = new SaxInternals(sessionContext);
|
|
}
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
internals.Dispose();
|
|
}
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Query Activity Index Entries for User Context.
|
|
//-------------------------------------------------------------------
|
|
private class ActivityData_Web : IndexResults.ActivityData
|
|
{
|
|
public ActivityData_Web(ItemId itemId, DateTime effectiveOn) : base(itemId, effectiveOn) { }
|
|
public void SetCaption(String caption) { Caption = caption; }
|
|
public void SetBlurb(String blurb) { Blurb = blurb; }
|
|
public void SetSport(SysId sportId, String sportName) { SportId = sportId; SportName = sportName; }
|
|
public void SetRegion(SysId regionId, String regionName) { RegionId = regionId; RegionName = regionName; }
|
|
public static int CompareActivityIndices(ActivityData_Web item1, ActivityData_Web item2)
|
|
{
|
|
int effectiveCompare = item1.EffectiveOn.CompareTo(item2.EffectiveOn);
|
|
if (effectiveCompare != 0) return effectiveCompare * -1;
|
|
return 1;
|
|
}
|
|
}
|
|
public override IndexResults QueryIndex(IndexContext context)
|
|
{
|
|
String fn = GetType().Name + ".QueryIndex";
|
|
IndexResults results = new IndexResults();
|
|
if (!context.IsValid()) return results;
|
|
|
|
// Columns to query.
|
|
ColumnDfn colItemType = internals.ActivityMgr.GetActivityIndexColumnDfn(SaxActivityIndex.Column.ItemType);
|
|
ColumnDfn colItemId = internals.ActivityMgr.GetActivityIndexColumnDfn(SaxActivityIndex.Column.ItemId);
|
|
String colDataNameEffectiveOn = "EffectiveOn";
|
|
|
|
// Query the index.
|
|
ISacsDatabase db = SaxGlobals.App.GetCoreDatabase(SessionContext);
|
|
DbQuery query = new DbQuery(db.DbmsType);
|
|
query.Tables.Add(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.ActivityIndex, false), alias_ActivityIndex);
|
|
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemType, alias_ActivityIndex), colItemType.DataName);
|
|
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemId, alias_ActivityIndex), colItemId.DataName);
|
|
query.Columns.Add("Max(" + SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_EffectiveOn, alias_ActivityIndex) + ")", colDataNameEffectiveOn);
|
|
query.GroupBy.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemType, alias_ActivityIndex));
|
|
query.GroupBy.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemId, alias_ActivityIndex));
|
|
query.OrderBy.Add("Max(" + SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_EffectiveOn, alias_ActivityIndex) + ") DESC");
|
|
|
|
// Filter.
|
|
SaxActivityIndex.Params prmActivityIndex = new SaxActivityIndex.Params();
|
|
prmActivityIndex.SportIdsIncluded.AddRange(context.SportIds);
|
|
prmActivityIndex.RegionIdsIncluded.AddRange(context.RegionIds);
|
|
prmActivityIndex.EffectiveFrom = context.EffectiveFrom;
|
|
prmActivityIndex.EffectiveTo = context.EffectiveTo;
|
|
prmActivityIndex.Alias_ActivityIndex = alias_ActivityIndex;
|
|
query.Filters.AddRange(internals.ActivityMgr.GetActivityIndexQueryFilter(prmActivityIndex));
|
|
|
|
// First pass, note the activity Item and effective date.
|
|
List<ActivityData_Web> activityDataList = new List<ActivityData_Web>();
|
|
using (DbResultSet dbResultSet = DbResultSet_DataReader.ExecuteQuery(db, query.BuildQuery(context.Paging)))
|
|
{
|
|
while (dbResultSet != null && dbResultSet.NextRecord())
|
|
{
|
|
NamedValue.Map values = dbResultSet.GetRecordValues();
|
|
Sax.DataItemType itemType = (Sax.DataItemType)values.GetLong(colItemType.DataName);
|
|
ItemId itemId = new ItemId((short)itemType, new SysId(values.GetLong(colItemId.DataName)));
|
|
DateTime effectiveOn = values.GetDate(colDataNameEffectiveOn);
|
|
activityDataList.Add(new ActivityData_Web(itemId, effectiveOn));
|
|
SaLogger.Info(fn + " Activity found - " + itemType.ToString() + ":" + SysId.ToString(itemId.Id) + ". Effective: " + DateUtil.Format(effectiveOn, "d-MMM-yyyy"));
|
|
}
|
|
}
|
|
activityDataList.Sort(ActivityData_Web.CompareActivityIndices);
|
|
|
|
// Populate activity details.
|
|
PopulateActivityDetails(activityDataList);
|
|
|
|
// ToDo Remove activities with blank caption.
|
|
|
|
results.Items.AddRange(activityDataList);
|
|
return results;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Populate Activity Details.
|
|
//-------------------------------------------------------------------
|
|
private void PopulateActivityDetails(List<ActivityData_Web> activities)
|
|
{
|
|
PopulateJournalistArticleDetails(activities);
|
|
PopulateOrganisationOpportunitiesDetails(activities);
|
|
}
|
|
private void PopulateJournalistArticleDetails(List<ActivityData_Web> activities)
|
|
{
|
|
// Extract article Ids.
|
|
List<SysId> articleIds = activities.FindAll(item => item.ItemId.Type == (int)Sax.DataItemType.JournalistArticle).Select(ItemId => ItemId.ItemId.Id).ToList();
|
|
if (articleIds.IsEmpty()) return;
|
|
|
|
// Article columns - limit to essential information.
|
|
ColumnDfn colId = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Id);
|
|
ColumnDfn colHeadline = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Headline);
|
|
ColumnDfn colSummary = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Summary);
|
|
ColumnDfn colSportId = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.SportIdPrimary);
|
|
ColumnDfn colSportName = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Sport_Name);
|
|
ColumnDfn colRegionId = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.RegionIdPrimary);
|
|
ColumnDfn colRegionName = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Region_Name);
|
|
List<ColumnDfn> columns = new List<ColumnDfn>() { colId, colHeadline, colSummary, colSportId, colSportName, colRegionId, colRegionName };
|
|
|
|
// Article filter.
|
|
SaxJournalistArticle.Params prmArticle = new SaxJournalistArticle.Params();
|
|
prmArticle.IdsIncluded.AddRange(articleIds);
|
|
prmArticle.StatusCat = SaxJournalistArticle.StatusCat.ActiveOnly;
|
|
|
|
using (DbResultSet dbResultSet = Internals.ActivityMgr.ExecuteJournalistArticleQuery(columns, prmArticle))
|
|
{
|
|
while (dbResultSet != null && dbResultSet.NextRecord())
|
|
{
|
|
NamedValue.Map values = dbResultSet.GetRecordValues();
|
|
ItemId itemId = new ItemId((short)Sax.DataItemType.JournalistArticle, new SysId(values.GetLong(colId.DataName)));
|
|
String headline = values.GetString(colHeadline.DataName);
|
|
String summary = values.GetString(colSummary.DataName);
|
|
SysId sportId = new SysId(values.GetLong(colSportId.DataName));
|
|
String sportName = values.GetString(colSportName.DataName);
|
|
SysId regionId = new SysId(values.GetLong(colRegionId.DataName));
|
|
String regionName = values.GetString(colRegionName.DataName);
|
|
|
|
// Populate to corresponding activities.
|
|
foreach (ActivityData_Web activity in activities.FindAll(item => item.ItemId.Equals(itemId)))
|
|
{
|
|
activity.SetCaption(headline);
|
|
activity.SetBlurb(summary);
|
|
activity.SetSport(sportId, sportName);
|
|
activity.SetRegion(regionId, regionName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private void PopulateOrganisationOpportunitiesDetails(List<ActivityData_Web> activities)
|
|
{
|
|
// Extract opportunity Ids.
|
|
List<SysId> opportunityIds = activities.FindAll(item => item.ItemId.Type == (int)Sax.DataItemType.OrganisationOpportunity).Select(ItemId => ItemId.ItemId.Id).ToList();
|
|
if (opportunityIds.IsEmpty()) return;
|
|
|
|
// Opportunity columns - limit to essential information.
|
|
ColumnDfn colId = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Id);
|
|
ColumnDfn colPosition = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Position);
|
|
ColumnDfn colOutline = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Outline);
|
|
ColumnDfn colSportId = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.SportIdPrimary);
|
|
ColumnDfn colSportName = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Sport_Name);
|
|
ColumnDfn colRegionId = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.RegionIdPrimary);
|
|
ColumnDfn colRegionName = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Region_Name);
|
|
List<ColumnDfn> columns = new List<ColumnDfn>() { colId, colPosition, colOutline, colSportId, colSportName, colRegionId, colRegionName };
|
|
|
|
// Opportunity filter.
|
|
SaxOrganisationOpportunity.Params prmOpportunity = new SaxOrganisationOpportunity.Params();
|
|
prmOpportunity.IdsIncluded.AddRange(opportunityIds);
|
|
prmOpportunity.StatusCat = SaxOrganisationOpportunity.StatusCat.ActiveOnly;
|
|
|
|
using (DbResultSet dbResultSet = Internals.ActivityMgr.ExecuteOrganisationOpportunityQuery(columns, prmOpportunity))
|
|
{
|
|
while (dbResultSet != null && dbResultSet.NextRecord())
|
|
{
|
|
NamedValue.Map values = dbResultSet.GetRecordValues();
|
|
ItemId itemId = new ItemId((short)Sax.DataItemType.OrganisationOpportunity, new SysId(values.GetLong(colId.DataName)));
|
|
String headline = values.GetString(colPosition.DataName);
|
|
String summary = values.GetString(colOutline.DataName);
|
|
SysId sportId = new SysId(values.GetLong(colSportId.DataName));
|
|
String sportName = values.GetString(colSportName.DataName);
|
|
SysId regionId = new SysId(values.GetLong(colRegionId.DataName));
|
|
String regionName = values.GetString(colRegionName.DataName);
|
|
|
|
// Populate to corresponding activities.
|
|
foreach (ActivityData_Web activity in activities.FindAll(item => item.ItemId.Equals(itemId)))
|
|
{
|
|
activity.SetCaption(headline);
|
|
activity.SetBlurb(summary);
|
|
activity.SetSport(sportId, sportName);
|
|
activity.SetRegion(regionId, regionName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Store Activity Index.
|
|
//-------------------------------------------------------------------
|
|
protected override bool StoreActivityIndexData(IndexData indexData, DbUpdateInfo dbUpdateInfo)
|
|
{
|
|
String fn = GetType().Name + ".StoreActivityIndexData";
|
|
if (!ItemId.IsValid(indexData.ItemId)) return false;
|
|
if (!ValidActivityItemTypes.Contains((Sax.DataItemType)indexData.ItemId.Type))
|
|
{
|
|
SaLogger.Warn(fn + " Invalid item type specified for Activity Index: " + ((Sax.DataItemType)indexData.ItemId.Type).ToString());
|
|
return false;
|
|
}
|
|
IndexStatsData stats = new IndexStatsData();
|
|
|
|
// Index entries required for activity.
|
|
List<IndexEntryData> indexEntries = GetEntriesForIndex(indexData);
|
|
|
|
// Retrieve existing index entries for the item.
|
|
List<SaxActivityIndex> itemIndexEntries = internals.ActivityMgr.GetActivityIndexListForItem(indexData.ItemId);
|
|
foreach (SaxActivityIndex itemIndexEntry in itemIndexEntries)
|
|
{
|
|
// Is the index entry still required.
|
|
// Logic only compares the Ids (item, sport, region) and then updates the effective date if a match is found.
|
|
// Based on the fact that and change in the effective date will impact all entries in the index for the item
|
|
// and this approach minimises the number of updates required as Ids can't be changed in code (protected setters).
|
|
IndexEntryData indexEntry = indexEntries.Find(item => item.MatchesIds(itemIndexEntry));
|
|
if (indexEntry != null)
|
|
{
|
|
// Match found - if the effective date differs, update it.
|
|
if (!itemIndexEntry.EffectiveOn.Equals(indexEntry.EffectiveOn))
|
|
{
|
|
itemIndexEntry.EffectiveOn = indexEntry.EffectiveOn;
|
|
if (internals.ActivityMgr.UpdateActivityIndex(itemIndexEntry, dbUpdateInfo))
|
|
stats.EntriesUpdated++;
|
|
else SaLogger.Warn(fn + " Failed to update Activity Index - " + internals.ActivityMgr.ErrorStateMessage);
|
|
}
|
|
// Remove the entry from the 'required' list.
|
|
// Entries remaining in this list will be created.
|
|
indexEntries.Remove(indexEntry);
|
|
}
|
|
else
|
|
{
|
|
// Index entry no longer required.
|
|
if (internals.ActivityMgr.DeleteActivityIndex(itemIndexEntry, dbUpdateInfo))
|
|
stats.EntriesDeleted++;
|
|
else SaLogger.Warn(fn + " Failed to delete Activity Index - " + internals.ActivityMgr.ErrorStateMessage);
|
|
}
|
|
}
|
|
// The remaining required Index entries will be created.
|
|
foreach (IndexEntryData indexEntry in indexEntries)
|
|
{
|
|
SaxActivityIndex itemIndexEntry = internals.ActivityMgr.CreateActivityIndex(indexEntry.ItemId, indexEntry.SportId, indexEntry.RegionId, indexEntry.EffectiveOn);
|
|
if (internals.ActivityMgr.InsertActivityIndex(itemIndexEntry, dbUpdateInfo))
|
|
stats.EntriesInserted++;
|
|
else SaLogger.Warn(fn + " Failed to insert Activity Index - " + internals.ActivityMgr.ErrorStateMessage);
|
|
}
|
|
|
|
// Log statistics.
|
|
List<String> statsLog = new List<string>();
|
|
if (stats.EntriesInserted > 0) statsLog.Add("Inserted: " + stats.EntriesInserted);
|
|
if (stats.EntriesUpdated > 0) statsLog.Add("Updated: " + stats.EntriesUpdated);
|
|
if (stats.EntriesDeleted > 0) statsLog.Add("Deleted: " + stats.EntriesDeleted);
|
|
SaLogger.Info(fn + " Activity Index stored for " + ((Sax.DataItemType)indexData.ItemId.Type).ToString() + ":" + indexData.ItemId.Id.ToLong() + "." + statsLog.Concat("", "", ". "));
|
|
|
|
return true;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
protected override bool ClearActivityIndex(ItemId itemId, DbUpdateInfo dbUpdateInfo)
|
|
{
|
|
String fn = GetType().Name + ".ClearActivityIndex";
|
|
String tableName = SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.ActivityIndex);
|
|
String filter =
|
|
SaxDbDfn_Core.GetColumnName(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemType) + "=" + itemId.Type +
|
|
" And " + SaxDbDfn_Core.GetColumnName(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemId) + "=" + itemId.Id.ToLong();
|
|
ISacsDatabase db = SaxGlobals.App.GetCoreDatabase(SessionContext);
|
|
int recordsDeleted = db.ExecuteDelete(tableName, filter);
|
|
SaLogger.Info(fn + " Records deleted: " + recordsDeleted + ". Filter: " + filter, true);
|
|
return true;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
//=======================================================================
|
|
}
|