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 Saxonite.Net.Standard.Dbas.Mgr; 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 String alias_ActivityIndex = SaxActivityMgr_Dbas.aliasActivityIndex; private readonly String alias_ActivityIndex_UserActivity = SaxActivityMgr_Dbas.aliasActivityIndex_UserActivity; 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) { } protected override void Dispose(bool disposing) { if (disposing) { } 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 SetOrganisation(SysId organisationId, String organisation) { OrganisationId = organisationId; Organisation = organisation; } public void SetAuthor(SysId userAccountId, String author) { UserAccountIdAuthor = userAccountId; Author = author; } 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; } // User Activity. public void SetLastListedAt(DateTime lastListedAt) { LastListedAt = lastListedAt; } public void SetLastViewedAt(DateTime lastViewedAt) { LastViewedAt = lastViewedAt; } public void SetReaction(Sax.ActivityReaction reaction) { Reaction = reaction; } public void SetLastReactedAt(DateTime lastReactedAt) { LastReactedAt = lastReactedAt; } 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"; ClearErrorState(); 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 Activity 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.UserAccountIdsOwnerIncluded.AddRange(context.UserAccountIdsOwner); prmActivityIndex.OrganisationIdsOwnerIncluded.AddRange(context.OrganisationIdsOwner); prmActivityIndex.SportRegionIdsIncluded.AddRange(context.SportRegionIdsIncluded); prmActivityIndex.EffectiveFrom = context.EffectiveFrom; prmActivityIndex.EffectiveTo = context.EffectiveTo; prmActivityIndex.NotExpiredOn = context.NotExpiredOn; prmActivityIndex.Alias_ActivityIndex = alias_ActivityIndex; prmActivityIndex.ResultsPaging.PageNo = 1; prmActivityIndex.ResultsPaging.PageLength = 100; query.Filters.AddRange(Internals.ActivityMgr.GetActivityIndexQueryFilter(prmActivityIndex)); // First pass, note the activity Item and effective date. List activityDataList = new List(); 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); ActivityData_Web activtyData = new ActivityData_Web(itemId, effectiveOn); activityDataList.Add(activtyData); SaLogger.Info(fn + " Activity found - " + itemType.ToString() + ":" + SysId.ToString(itemId.Id) + ". Effective: " + DateUtil.Format(effectiveOn, "d-MMM-yyyy")); } } // Sort the activity list. activityDataList.Sort(ActivityData_Web.CompareActivityIndices); // Populate activity details. PopulateActivityDetails(context, activityDataList); // ToDo Remove activities with blank caption. results.Items.AddRange(activityDataList); return results; } //------------------------------------------------------------------- // Populate Activity Details. //------------------------------------------------------------------- private void PopulateActivityDetails(IndexContext context, List activities) { PopulateUserActivityDetails(context, activities); PopulateArticleDetails(context, activities); PopulateOrganisationEventDetails(context, activities); PopulateOrganisationOpportunityDetails(context, activities); } //------------------------------------------------------------------- private void PopulateUserActivityDetails(IndexContext context, List activities) { // Validate parameters. if (!SysId.IsValid(context.UserAccountId)) return; // Extract article Ids. List activityItemIds = activities.Select(item => new ItemId(item.ItemId.Type, item.ItemId.Id)).ToList(); if (activityItemIds.IsEmpty()) return; // User Activity columns - limit to essential information. ColumnDfn colItemType = Internals.ActivityMgr.GetUserActivityColumnDfn(SaxUserActivity.Column.ItemType); ColumnDfn colItemId = Internals.ActivityMgr.GetUserActivityColumnDfn(SaxUserActivity.Column.ItemId); ColumnDfn colUserAccountId = Internals.ActivityMgr.GetUserActivityColumnDfn(SaxUserActivity.Column.UserAccountId); ColumnDfn colLastListedAt = Internals.ActivityMgr.GetUserActivityColumnDfn(SaxUserActivity.Column.LastListedAt); ColumnDfn colLastViewedAt = Internals.ActivityMgr.GetUserActivityColumnDfn(SaxUserActivity.Column.LastViewedAt); ColumnDfn colReaction = Internals.ActivityMgr.GetUserActivityColumnDfn(SaxUserActivity.Column.Reaction); ColumnDfn colLastReactedAt = Internals.ActivityMgr.GetUserActivityColumnDfn(SaxUserActivity.Column.LastReactedAt); List columns = new List() { colItemType, colItemId, colUserAccountId, colLastListedAt, colLastViewedAt, colReaction, colLastReactedAt }; // User Activity filter. SaxUserActivity.Params prmUserActivity = new SaxUserActivity.Params(); prmUserActivity.UserAccountIdsIncluded.Add(context.UserAccountId); prmUserActivity.ItemIdsIncluded.AddRange(activityItemIds); prmUserActivity.StatusCat = SaxUserActivity.StatusCat.ActiveOnly; using (DbResultSet dbResultSet = Internals.ActivityMgr.ExecuteUserActivityQuery(columns, prmUserActivity)) { while (dbResultSet != null && dbResultSet.NextRecord()) { NamedValue.Map values = dbResultSet.GetRecordValues(); ItemId activityItemId = new ItemId((short)values.GetLong(colItemType.DataName), new SysId(values.GetLong(colItemId.DataName))); DateTime lastListedAt = values.GetDateTime(colLastListedAt.DataName); DateTime lastViewedAt = values.GetDateTime(colLastViewedAt.DataName); Sax.ActivityReaction reaction = (Sax.ActivityReaction)values.GetLong(colReaction.DataName); DateTime lastReactedAt = values.GetDateTime(colLastReactedAt.DataName); // Populate to corresponding activities. foreach (ActivityData_Web activity in activities.FindAll(item => item.ItemId.Equals(activityItemId))) { activity.SetLastListedAt(lastListedAt); activity.SetLastViewedAt(lastViewedAt); activity.SetReaction(reaction); activity.SetLastReactedAt(lastReactedAt); } } } } //------------------------------------------------------------------- // Article details. private void PopulateArticleDetails(IndexContext context, List activities) { // Extract article Ids. List articleIds = activities.FindAll(item => item.ItemId.Type == (int)Sax.DataItemType.Article).Select(ItemId => ItemId.ItemId.Id).ToList(); if (articleIds.IsEmpty()) return; // Article columns - limit to essential information. ColumnDfn colId = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Id); ColumnDfn colOrganisationId = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.OrganisationId); ColumnDfn colOrganisation = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Organisation_Name); ColumnDfn colAuthorId = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.UserAccountIdAuthor); ColumnDfn colAuthor = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Author_DisplayName); ColumnDfn colHeadline = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Headline); ColumnDfn colSummary = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Summary); ColumnDfn colSportId = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.SportIdPrimary); ColumnDfn colSportName = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Sport_Name); ColumnDfn colRegionId = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.RegionIdPrimary); ColumnDfn colRegionName = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Region_Name); List columns = new List() { colId, colOrganisationId, colOrganisation, colAuthor, colAuthorId, colHeadline, colSummary, colSportId, colSportName, colRegionId, colRegionName }; // Article filter. SaxArticle.Params prmArticle = new SaxArticle.Params(); prmArticle.IdsIncluded.AddRange(articleIds); prmArticle.StatusCat = SaxArticle.StatusCat.ActiveOnly; using (DbResultSet dbResultSet = Internals.ActivityMgr.ExecuteArticleQuery(columns, prmArticle)) { while (dbResultSet != null && dbResultSet.NextRecord()) { NamedValue.Map values = dbResultSet.GetRecordValues(); ItemId itemId = new ItemId((short)Sax.DataItemType.Article, new SysId(values.GetLong(colId.DataName))); SysId organisationId = new SysId(values.GetLong(colOrganisationId.DataName)); String organisation = values.GetString(colOrganisation.DataName); SysId authorId = new SysId(values.GetLong(colAuthorId.DataName)); String author = values.GetString(colAuthor.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.SetOrganisation(organisationId, organisation); activity.SetAuthor(authorId, author); activity.SetCaption(headline); activity.SetCaption(headline); activity.SetBlurb(summary); activity.SetSport(sportId, sportName); activity.SetRegion(regionId, regionName); } } } } //------------------------------------------------------------------- // Organisation Event details. private void PopulateOrganisationEventDetails(IndexContext context, List activities) { // Extract organisationEvent Ids. List organisationEventIds = activities.FindAll(item => item.ItemId.Type == (int)Sax.DataItemType.OrganisationEvent).Select(ItemId => ItemId.ItemId.Id).ToList(); if (organisationEventIds.IsEmpty()) return; // Event columns - limit to essential information. ColumnDfn colId = Internals.ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.Id); ColumnDfn colOrganisationId = Internals.ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.OrganisationId); ColumnDfn colOrganisation = Internals.ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.Organisation_Name); ColumnDfn colEventAt = Internals.ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.EventAt_DateTime); ColumnDfn colSummary = Internals.ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.Summary); ColumnDfn colDetails = Internals.ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.Details); ColumnDfn colSportId = Internals.ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.SportIdPrimary); ColumnDfn colSportName = Internals.ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.Sport_Name); ColumnDfn colRegionId = Internals.ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.RegionIdCountry); ColumnDfn colRegionName = Internals.ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.Region_Name); List columns = new List() { colId, colOrganisationId, colOrganisation, colEventAt, colSummary, colDetails, colSportId, colSportName, colRegionId, colRegionName }; // Event filter. SaxOrganisationEvent.Params prmEvent = new SaxOrganisationEvent.Params(); prmEvent.IdsIncluded.AddRange(organisationEventIds); prmEvent.StatusCat = SaxOrganisationEvent.StatusCat.ActiveOnly; using (DbResultSet dbResultSet = Internals.ActivityMgr.ExecuteOrganisationEventQuery(columns, prmEvent)) { while (dbResultSet != null && dbResultSet.NextRecord()) { NamedValue.Map values = dbResultSet.GetRecordValues(); ItemId itemId = new ItemId((short)Sax.DataItemType.OrganisationEvent, new SysId(values.GetLong(colId.DataName))); SysId organisationId = new SysId(values.GetLong(colOrganisationId.DataName)); String organisation = values.GetString(colOrganisation.DataName); DateTime eventAt = values.GetDateTime(colEventAt.DataName); String eventAtDisplay = DateUtil.Format(eventAt, "d-MMM-yy"); if (eventAt.Hour > 0 || eventAt.Minute > 0) eventAtDisplay += DateUtil.Format(values.GetDateTime(colEventAt.DataName), " HH:mm"); String eventSummary = values.GetString(colSummary.DataName); String eventDetails = values.GetString(colDetails.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.SetOrganisation(organisationId, organisation); activity.SetCaption(eventAtDisplay); activity.SetBlurb(eventSummary); activity.SetSport(sportId, sportName); activity.SetRegion(regionId, regionName); } } } } //------------------------------------------------------------------- // Organisation Opportunity details. private void PopulateOrganisationOpportunityDetails(IndexContext context, List activities) { // Extract opportunity Ids. List 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 colOrganisationId = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.OrganisationId); ColumnDfn colOrganisation = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Organisation_Name); 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 columns = new List() { colId, colOrganisationId, colOrganisation, 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))); SysId organisationId = new SysId(values.GetLong(colOrganisationId.DataName)); String organisation = values.GetString(colOrganisation.DataName); String position = values.GetString(colPosition.DataName); String outline = 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.SetOrganisation(organisationId, organisation); activity.SetCaption(position); activity.SetBlurb(outline); activity.SetSport(sportId, sportName); activity.SetRegion(regionId, regionName); } } } } //------------------------------------------------------------------- // Store Activity Index. //------------------------------------------------------------------- protected override bool StoreActivityIndexData(IndexData indexData, DbUpdateInfo dbUpdateInfo) { String fn = GetType().Name + ".StoreActivityIndexData"; ClearErrorState(); // Validate paramaters. 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 SetErrorState("Invalid item type specified for Activity Index"); } IndexStatsData stats = new IndexStatsData(); // Index entries required for activity. List indexEntryDataList = GetEntriesForIndex(indexData); // Retrieve existing index entries for the item. List indexEntries = Internals.ActivityMgr.GetActivityIndexListForItem(indexData.ItemId); foreach (SaxActivityIndex indexEntry in indexEntries) { // 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 indexEntrydata = indexEntryDataList.Find(item => item.MatchesIds(indexEntry)); if (indexEntrydata != null) { // Match found - update properties. indexEntry.UserAccountIdOwner = indexEntrydata.UserAccountIdOwner; indexEntry.OrganisationIdOwner = indexEntrydata.OrganisationIdOwner; indexEntry.EffectiveOn = indexEntrydata.EffectiveOn; indexEntry.ExpiresOn = indexEntrydata.ExpiresOn; if (indexEntry.Changed) { if (Internals.ActivityMgr.UpdateActivityIndex(indexEntry, 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. indexEntryDataList.Remove(indexEntrydata); } else { // Index entry no longer required. if (Internals.ActivityMgr.DeleteActivityIndex(indexEntry, 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 indexEntryDataList) { SaxActivityIndex itemIndexEntry = Internals.ActivityMgr.CreateActivityIndex(indexEntry.ItemId, indexEntry.SportId, indexEntry.RegionId); itemIndexEntry.UserAccountIdOwner = indexEntry.UserAccountIdOwner; itemIndexEntry.OrganisationIdOwner = indexEntry.OrganisationIdOwner; itemIndexEntry.EffectiveOn = indexEntry.EffectiveOn; itemIndexEntry.ExpiresOn = indexEntry.ExpiresOn; if (Internals.ActivityMgr.InsertActivityIndex(itemIndexEntry, dbUpdateInfo)) stats.EntriesInserted++; else SaLogger.Warn(fn + " Failed to insert Activity Index - " + Internals.ActivityMgr.ErrorStateMessage); } // Log statistics. List statsLog = new List(); 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"; ClearErrorState(); 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); if (recordsDeleted > 0) SaLogger.Info(fn + " Records deleted: " + recordsDeleted + ". Filter: " + filter, true); return true; } //------------------------------------------------------------------- // User Activities //------------------------------------------------------------------- /// /// Record listing of activities by user - those populated to the application page. /// - Activities not previously listed are added to the user's list. /// - Activities previously listed are updated in the user's list. /// - User Activities no longer listed are flagged as 'Not currently listed'. /// public override bool RecordUserActivitiesListed(SysId userAccountId, List activityItemIds, DbUpdateInfo dbUpdateInfo) { String fn = GetType().Name + ".RecordUserActivitiesListed"; if (!SysId.IsValid(userAccountId)) return SetErrorState("User Account must be specified"); if (activityItemIds.IsEmpty()) return SetErrorState("Activity item ids must be specified"); String sqlNow = "'" + DateUtil.FormatSqlDateTime(DateTime.Now) + "'"; String sqlStatus = "'" + SacsSystem.GetStatusCode(SaxUserActivity.DefaultStatus) + "'"; // Merge query - insert missing user activities and update existing. List query = new List() { "Merge", "\tInto " + SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.UserActivity) + " As UsrAct", // Virtual table defining Activity Item Ids currently listed. "\tUsing", "\t(", "\t\tSelect ItemType, ItemId From (Select 0 ItemType, 0 ItemId" + activityItemIds.Select(item => " Union Select " + item.Type.ToString() + ", " + item.Id.ToString()).ToList().Concat("", " ") + ") Dat Where Dat.ItemType>0 And Dat.ItemId>0", "\t) As Act", "\tOn UsrAct.UserAccountId="+userAccountId.ToString() + " And UsrAct.ItemType=Act.ItemType And UsrAct.ItemId=Act.ItemId", // Matched - Update the User Activity to indicate 'Currently listed' and update the last listed date/time. "\tWhen Matched Then", "\t\tUpdate Set CurrentlyListed=1, ListedAtLast=" + sqlNow + ", Status=" + sqlStatus + ", UpdateOn=" + sqlNow + ", UpdateBy=" + dbUpdateInfo.UserId.ToString() + ", UpdateHost='" + dbUpdateInfo.Host + "'", // Not Matched By Target - Insert the User Activity and indicate 'Currently listed' with first and last listed date/times. "\tWhen Not Matched Then", "\t\tInsert", "\t\t\t(UserAccountId, ItemType, ItemId, CurrentlyListed, ListedAtFirst, ListedAtLast, Reaction, UserActivityData, Notes, Flags, Status, CreateOn, CreateBy, CreateHost, UpdateOn, UpdateBy, UpdateHost)", "\t\t\tValues ("+userAccountId.ToString()+", Act.ItemType, Act.ItemId, 1, " + sqlNow + ", " + sqlNow + ", 0, '', '', 0, " + sqlStatus + ", " + sqlNow + ", " + dbUpdateInfo.UserId.ToString() + ", '" + dbUpdateInfo.Host + "', " + sqlNow + ", " + dbUpdateInfo.UserId.ToString() + ", '" + dbUpdateInfo.Host + "')", // Not Matched By Source - Update the User Activity to indicate 'Not currently listed'. "\tWhen Not Matched By Source And UsrAct.UserAccountId=" + userAccountId.ToString() + " And CurrentlyListed=1 Then", "\t\tUpdate Set CurrentlyListed=0, UpdateOn=" + sqlNow + ", UpdateBy=" + dbUpdateInfo.UserId.ToString() + ", UpdateHost='" + dbUpdateInfo.Host + "'", ";" }; String sql = query.Concat("\n"); //SaLogger.Debug(fn + " Query:\n" + sql); ISacsDatabase db = SaxGlobals.App.GetCoreDatabase(SessionContext); int rows = db.ExecuteNonQuery(sql); if (db.HasErrorState()) SaLogger.Debug(fn + " Database error: " + db.ErrorStateMessage); SaLogger.Debug(fn + " Rows modified: " + rows); return true; } //------------------------------------------------------------------- public override bool RecordUserActivityViewed(SysId userAccountId, ItemId activityItemId, DbUpdateInfo dbUpdateInfo) { String fn = GetType().Name + ".RecordUserActivityViewed"; if (!SysId.IsValid(userAccountId)) return SetErrorState("User Account must be specified"); if (!ItemId.IsValid(activityItemId)) return SetErrorState("Activity item id must be specified"); DateTime now = DateTime.Now; SaxUserActivity userActivity = Internals.ActivityMgr.GetUserActivityForUserItem(userAccountId, activityItemId); if (userActivity != null) { // Update activity. userActivity.CurrentlyListed = true; if (!DateUtil.IsValid(userActivity.ViewedAtFirst)) userActivity.ViewedAtFirst = now; userActivity.ViewedAtLast = now; userActivity.Status = SaxUserActivity.DefaultStatus; if (!Internals.ActivityMgr.UpdateUserActivity(userActivity, dbUpdateInfo)) { SaLogger.Warn(fn + " Failed to update User Activity for viewing: " + Internals.ActivityMgr.ErrorStateMessage); return SetErrorState(Internals.ActivityMgr.ErrorStateMessage); } } else { SaLogger.Warn(fn + " User Activity not found. UserAccountId: " + userAccountId.ToString() + ". Item Type: " + (Sax.DataItemType)activityItemId.Type + ". ItemId: " + activityItemId.Id.ToString() + "."); return SetErrorState("User Activity not found"); } return true; } //------------------------------------------------------------------- public override bool RecordUserActivityReaction(SysId userAccountId, ItemId activityItemId, Sax.ActivityReaction activityReaction, DbUpdateInfo dbUpdateInfo) { String fn = GetType().Name + ".RecordUserActivityReaction"; if (!SysId.IsValid(userAccountId)) return SetErrorState("User Account must be specified"); if (!ItemId.IsValid(activityItemId)) return SetErrorState("Activity item id must be specified"); DateTime now = DateTime.Now; SaxUserActivity userActivity = Internals.ActivityMgr.GetUserActivityForUserItem(userAccountId, activityItemId); if (userActivity != null) { if (userActivity.Reaction != activityReaction) { // Update activity. userActivity.CurrentlyListed = true; if (!DateUtil.IsValid(userActivity.ViewedAtFirst)) userActivity.ViewedAtFirst = now; userActivity.ViewedAtLast = now; userActivity.Reaction = activityReaction; if (!DateUtil.IsValid(userActivity.ReactedAtFirst)) userActivity.ReactedAtFirst = now; userActivity.ReactedAtLast = now; userActivity.Status = SaxUserActivity.DefaultStatus; if (!Internals.ActivityMgr.UpdateUserActivity(userActivity, dbUpdateInfo)) { SaLogger.Warn(fn + " Failed to update User Activity with reaction: " + Internals.ActivityMgr.ErrorStateMessage); return SetErrorState(Internals.ActivityMgr.ErrorStateMessage); } } } else { SaLogger.Warn(fn + " User Activity not found. UserAccountId: " + userAccountId.ToString() + ". Item Type: " + (Sax.DataItemType)activityItemId.Type + ". ItemId: " + activityItemId.Id.ToString() + "."); return SetErrorState("User Activity not found"); } return true; } //------------------------------------------------------------------- } //======================================================================= }