FlexitimeTracker/DataCenter_Windows/WindowsDataCenter/SQLiteRepository/SQLiteRepository.cs
Chris.Watts90@outlook.com f871c23631 add converters to help convert from/to data transfer objects.
removed conversion code from SQLiteRepository.cs in favour of new converters.
pulled out string queries from SQLiteRepository and moved to SQLiteProcedures.cs.
#95
2018-06-04 11:07:29 +01:00

883 lines
33 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using Interfaces;
using SQLite.Net;
using SQLite.Net.Platform.Win32;
using SQLiteRepository.Converters;
using SQLiteRepository.Properties;
namespace SQLiteRepository
{
public class SQLiteRepository : IRepository
{
private readonly SQLiteConnection _connection;
private readonly ILogger _logger;
private readonly string _path;
private const string DATABASE_NAME = "flexitimedb.db";
public SQLiteRepository(ILogger logger)
{
_path =
new Uri(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().CodeBase), DATABASE_NAME))
.LocalPath;
if (logger == null) throw new ArgumentNullException(nameof(logger));
_logger = logger;
_connection = new SQLiteConnection(new SQLitePlatformWin32(), _path);
_connection.CreateTable<CardUniqueId>();
_connection.CreateTable<UserIdentity>();
_connection.CreateTable<TimeLogDb>();
_connection.CreateTable<GroupDb>();
_connection.CreateTable<UserGroupJoinDb>();
_connection.CreateTable<DbVersion>();
_logger.Trace("Initialised SQLite Repository");
_logger.Trace("Checking For Upgrades");
CheckForDbUpgrade();
}
public UserList GetUsers(int pageNumber = -1, int pageSize = -1, int groupId = -1)
{
var ret = new UserList();
List<UserIdentity> users;
int userCount;
if (pageNumber != -1 && pageSize != -1)
{
users = _connection.Query<UserIdentity>(SQLiteProcedures.GET_ALL_USERS_PAGINATE,
pageSize, (pageNumber - 1) * pageSize);
userCount = _connection.ExecuteScalar<int>(SQLiteProcedures.GET_TOTAL_USER_COUNT);
}
else if (groupId != -1)
{
users =
_connection.Query<UserIdentity>(
SQLiteProcedures.GET_ALL_USERS_BY_GROUP,
groupId);
userCount = users.Count;
}
else
{
users = _connection.Query<UserIdentity>(SQLiteProcedures.GET_ALL_USERS);
userCount = users.Count;
}
if (!users.Any())
{
if (pageNumber == -1 && pageSize == -1)
{
ret.PageNumber = 1;
ret.PageSize = 20;
}
else
{
ret.PageNumber = pageNumber;
ret.PageSize = pageSize;
}
return ret;
}
foreach (var user in users)
{
var userObj = UserConverter.ConvertToUserDto(user);
userObj.AssociatedIdentifiers = GetAssociatedIdentifiers(user.Id);
userObj.State = GetUserState(GetLogDirection(user.Id));
userObj.LastEventDateTime = GetLastLogDateTime(GetLastTimeLog(user.Id));
userObj.Groups = GetGroups(user.Id);
ret.Users.Add(userObj);
}
if (pageNumber == -1 && pageSize == -1)
{
ret.PageSize = 10;
ret.PageNumber = 1;
}
else
{
ret.PageSize = pageSize;
ret.PageNumber = pageNumber;
}
ret.TotalUserCount = userCount;
return ret;
}
public UserList Search(string searchParam)
{
_logger.Trace("Searching SQLite database for the term: {0}", searchParam);
var ret = new UserList();
searchParam = string.Format("%{0}%", searchParam);
var users = _connection.Query<UserIdentity>(
SQLiteProcedures.SEARCH_USER_LIST,
searchParam, searchParam);
_logger.Trace("Got {0} results for term: {1}", users.Count, searchParam);
if (!users.Any())
{
ret.PageNumber = 1;
ret.PageSize = 20;
return ret;
}
foreach (var user in users)
{
var userObj = UserConverter.ConvertToUserDto(user);
var cards = _connection.Query<CardUniqueId>(
SQLiteProcedures.GET_CARDS_BY_USER_ID,
user.Id);
foreach (var card in cards)
{
userObj.AssociatedIdentifiers.Add(IdentifierConverter.ConvertToIdentifierDto(card));
//userObj.AssociatedIdentifiers.Add(new Identifier()
//{
// UniqueId = card.CardUId,
// IsAssociatedToUser = true,
// Id = card.Id
//});
}
userObj.State = GetUserState(GetLogDirection(user.Id));
ret.Users.Add(userObj);
}
//TODO: figure out paging here. - should there be any?
ret.PageSize = 20;
ret.PageNumber = 1;
return ret;
}
public User GetUser(int id)
{
var ret = new User();
try
{
var users = _connection.Query<UserIdentity>(
SQLiteProcedures.GET_USER_BY_ID,
id);
if (!users.Any()) return ret;
var user = users.First();
ret = UserConverter.ConvertToUserDto(user);
ret.Groups = GetGroups();
var usersGroups = GetGroups(user.Id);
foreach (var group in usersGroups)
{
ret.Groups.First(x => x.Id == group.Id).IsAssociatedToUser = true;
}
var cards = _connection.Query<CardUniqueId>(
SQLiteProcedures.GET_CARDS_BY_USER_ID,
user.Id);
foreach (var card in cards)
{
ret.AssociatedIdentifiers.Add(IdentifierConverter.ConvertToIdentifierDto(card));
//new Identifier
//{
// UniqueId = card.CardUId,
// IsAssociatedToUser = true,
// Id = card.Id
//});
}
}
catch (Exception ex)
{
_logger.Error(ex, "Error in GetUser with Id: {0}", id);
ret.UserId = id;
ret.FirstName = ret.LastName = string.Empty;
ret.HoursPerWeek = -1.0f;
ret.IsContractor = false;
ret.AssociatedIdentifiers.Clear();
}
return ret;
}
public TimeLogList GetTimeLogs(int userId)
{
return GetTimeLogs(userId, DateTime.UtcNow);
}
public TimeLogList GetTimeLogs(int userId, DateTime selectedDate)
{
var ret = new TimeLogList { SelectedDate = selectedDate.Date };
var calendarWeek = GetIso8601CalendarWeek(selectedDate);
ret.CalendarWeek = calendarWeek;
try
{
ret.TimeLogs = GetTimeLogList(userId, calendarWeek, selectedDate.Year);
}
catch (Exception ex)
{
_logger.Error(ex, "Error in GetTimeLogs with Id: {0} and selected date: {1}, Exception: {2}", userId, selectedDate, ex);
}
try
{
ret.HoursPerWeekMinutes = GetUserContractedHours(userId) * 60.0f;
}
catch (Exception ex)
{
_logger.Error(ex, "Error in GetUserContracterHours with Id: {0} and selected date: {1}, Exception: {2}", userId, selectedDate, ex);
}
ret.UserInformation = GetUser(userId);
return ret;
}
private float GetUserContractedHours(int userId)
{
var hoursQuery = _connection.Query<UserIdentity>(SQLiteProcedures.GET_USER_CONTRACTED_HOURS, userId);
if (hoursQuery.Any())
{
return hoursQuery.First().HoursPerWeek;
}
return -1.0f;
}
public IdentifierList GetUnassignedIdentifierList()
{
var ret = new IdentifierList();
var cardQuery = _connection.Query<CardUniqueId>(
SQLiteProcedures.GET_UNASSIGNED_CARD_LIST,
Constants.UNASSIGNED_CARD_USER_ID);
foreach (var card in cardQuery)
{
ret.data.Add(IdentifierConverter.ConvertToIdentifierDto(card));
// new Identifier
//{
// Id = card.Id,
// IsAssociatedToUser = card.UserId_FK != Constants.UNASSIGNED_CARD_USER_ID,
// UniqueId = card.CardUId,
// LastUsed = card.LastUsed.DateTime
//});
}
return ret;
}
public void ClearUnassignedIdentifiers()
{
_connection.Execute(
SQLiteProcedures.CLEAR_UNASSIGNED_CARDS,
Constants.UNASSIGNED_CARD_USER_ID);
}
//TODO: Check time logs table on update to ensure associated cards/unique identifiers are removed/added as appropriate.
public OperationResponse UpdateUser(User user, out int userIdResult)
{
var ret = OperationResponse.NONE;
var cardIds = new List<int>();
//Get a list of current associated identifiers, convert into a list of Identifier Objects..
var currentCards =
_connection.Query<CardUniqueId>(SQLiteProcedures.GET_CARDS_BY_USER_ID, user.UserId)
.Select(IdentifierConverter.ConvertToIdentifierDto);
var cardsToRemove = currentCards.Except(user.AssociatedIdentifiers).Select(x => x.Id).ToList();
#region GetUnique Identifiers
foreach (var card in user.AssociatedIdentifiers)
{
var existingCard = _connection.Query<CardUniqueId>(
SQLiteProcedures.GET_CARDS_BY_UNIQUE_ID, card.UniqueId);
if (!existingCard.Any())
{
var cardInsert = IdentifierConverter.ConvertFromIdentifierDto(card, Constants.UNASSIGNED_CARD_USER_ID);
_connection.Insert(cardInsert);
cardIds.Add(cardInsert.Id);
if (ret < OperationResponse.CREATED)
ret = OperationResponse.CREATED; //only change it if my status supercedes.
}
else
{
cardIds.Add(existingCard.First().Id);
if (ret < OperationResponse.UPDATED)
ret = OperationResponse.UPDATED;
}
}
#endregion
#region Update/Create User
int userId;
if (user.UserId != -1)
{
//edit..
_connection.Query<UserIdentity>(
SQLiteProcedures.UPDATE_USER_DETAILS,
user.FirstName,
user.LastName,
user.HoursPerWeek,
user.IsContractor,
user.UserId
);
userId = user.UserId;
}
else
{
var userInsert = UserConverter.ConvertFromUserDto(user);
_connection.Insert(userInsert);
userId = userInsert.Id;
if (ret < OperationResponse.CREATED)
ret = OperationResponse.CREATED;
}
#endregion
#region Update Card/Unique Id entries.
foreach (var cardId in cardIds)
{
_connection.Query<CardUniqueId>(
SQLiteProcedures.UPDATE_CARD_USER_ID,
userId, cardId);
}
foreach (var card in cardsToRemove)
{
_connection.Query<CardUniqueId>(
SQLiteProcedures.UPDATE_CARD_USER_ID,
Constants.UNASSIGNED_CARD_USER_ID, card);
}
#endregion
#region Update Group Associations
SetUserGroups(userId, user.Groups.Where(x => x.IsAssociatedToUser).ToList());
#endregion
userIdResult = userId;
return ret;
}
public LogEventResponse LogEventTime(Identifier identifier, out int logId)
{
var ret = new LogEventResponse();
var cardIdQuery = _connection.Query<CardUniqueId>(
SQLiteProcedures.GET_CARDS_BY_UNIQUE_ID,
identifier.UniqueId);
#region Get/Insert the PK Id Identifier to associate the time log to.
var ident = new CardUniqueId();
if (!cardIdQuery.Any())
{
//new card, create it!
ident.UserId_FK = -1;
ident.CardUId = identifier.UniqueId;
_connection.Insert(ident);
UpdateIdentifierLastUsed(DateTimeOffset.UtcNow, ident.Id);
logId = -1;
//dont try to log any timelogs against this card, as it is unassigned to a user.
ret.ProcessResponse=OperationResponse.SUCCESS;
ret.Direction = LogDirection.UNKNOWN;
return ret;
}
else
{
//TODO: log when more than one comes back. should NEVER happen but....
ident = cardIdQuery.First();
}
#endregion
// Get The User Direction (are they going in or out)?
var logDirection = GetLogDirection(ident.UserId_FK);
#region Check the user hasnt registered an event in the last few minutes..
if (ident.UserId_FK != -1)
{ //only check log gap if the card is associated to a user
var hysteresisThresholdMinutes = Convert.ToInt32(ConfigurationHandler.ConfigurationHandler.GetConfiguration("SwipeTimeGap") ?? "3");
var threshold = DateTime.UtcNow.AddMinutes(0 - hysteresisThresholdMinutes);
var logs = _connection.Query<TimeLogDb>(
SQLiteProcedures.GET_LOGS_IN_LAST_X_MINUTES,
threshold.Ticks, ident.UserId_FK);
_logger.Trace("Checking last swipe event gap");
if (logs.Any())
{
_logger.Error("Not logging event for user id: {0}, logged event within TimeGap Threshold of {1}", ident.UserId_FK, threshold);
logId = -1;
ret.ProcessResponse = OperationResponse.FAILED;
ret.Direction = LogDirection.UNKNOWN;
return ret;
}
}
#endregion
#region Get the current time (for swiping). and calendar week/year to help recall the data.
var logTime = DateTime.UtcNow;
var calendarWeek = GetIso8601CalendarWeek(logTime);
var year = logTime.Year;
#endregion
var timeLog = new TimeLogDb
{
SwipeEventDateTime = DateTime.UtcNow,
UserId_FK = ident.UserId_FK,
IdentifierId = ident.Id,
Direction = logDirection,
Year = year,
CalendarWeek = calendarWeek,
Source = LogSourceDb.IDENTIFIER
};
_connection.Insert(timeLog);
UpdateIdentifierLastUsed(timeLog.SwipeEventDateTime, timeLog.IdentifierId);
logId = timeLog.Id;
ret.Direction = (LogDirection)(int)logDirection;
ret.ProcessResponse = OperationResponse.SUCCESS;
return ret;
}
/*Groups*/
//TODO: check group name can only be entered once.
public OperationResponse CreateGroup(Group group, out int groupId)
{
var groupDb = new GroupDb { GroupName = group.Name };
var resp = _connection.Insert(groupDb);
groupId = groupDb.GroupId;
return OperationResponse.CREATED;
}
public List<Group> GetGroups(int userId = -1)
{
var ret = new List<Group>();
List<GroupDb> query;
if (userId == -1)
{
query = _connection.Query<GroupDb>(SQLiteProcedures.GET_GROUPS);
}
else
{
query =
_connection.Query<GroupDb>(SQLiteProcedures.GET_GROUPS_FOR_USER,
userId);
}
foreach (var group in query)
{
ret.Add(new Group
{
Id = group.GroupId,
Name = group.GroupName,
UserCount = int.Parse(group.AssignedUserCount ?? "0")
});
}
return ret;
}
public Group GetGroup(int groupId)
{
var query = _connection.Query<GroupDb>(SQLiteProcedures.GET_GROUP_BY_ID, groupId);
if (query.Any())
{
var group = query.First();
return new Group
{
Id = group.GroupId,
Name = group.GroupName,
UserCount = 0
};
}
return new Group();
}
public OperationResponse UpdateGroup(Group group)
{
var resp = _connection.Query<GroupDb>(SQLiteProcedures.UPDATE_GROUP, group.Name, group.Id);
return OperationResponse.UPDATED;
}
public OperationResponse DeleteGroup(int groupId)
{
_connection.Delete<GroupDb>(groupId);
return OperationResponse.DELETED;
}
public OperationResponse DeleteLog(TimeLog log)
{
var query = _connection.Query<TimeLogDb>(
SQLiteProcedures.GET_TIMELOG_ENTRY, log.Id);
if (!query.Any())
return OperationResponse.FAILED;
UpdateExistingLogDirections(log);
_connection.ExecuteScalar<TimeLogDb>(SQLiteProcedures.DELETE_TIMELOG_ENTRY, log.Id);
return OperationResponse.DELETED;
}
public OperationResponse CreateLog(TimeLog log)
{
log.CalendarWeek = GetIso8601CalendarWeek(log.EventTime.UtcDateTime);
log.Year= log.EventTime.Year;
var dbLog = TimeLogConverter.ConvertFromTimeLogDto(log);
dbLog.IdentifierId = ConvertSourceToIdentifierId(log.Source);
#region update in/out directions for manual logs.
UpdateExistingLogDirections(log);
#endregion
//and now insert the new log.
_connection.Insert(dbLog);
return OperationResponse.CREATED;
}
public OperationResponse UpdateLog(TimeLog log)
{
var query = _connection.Query<TimeLogDb>(
SQLiteProcedures.GET_TIMELOG_ENTRY, log.Id);
if(!query.Any())
return OperationResponse.FAILED;
if (log.CalendarWeek > 52 || log.CalendarWeek < 1)
{
log.CalendarWeek = GetIso8601CalendarWeek(log.EventTime.UtcDateTime);
}
if (log.Year < 2017)
{
log.Year = log.EventTime.Year;
}
_connection.ExecuteScalar<TimeLogDb>(
SQLiteProcedures.UPDATE_TIMELOG_ENTRY,
log.UserId, (LogDirectionDb) (int) log.Direction, log.EventTime, log.CalendarWeek, log.Year,
(LogSourceDb) (int) log.Source, log.Id);
return OperationResponse.UPDATED;
}
private void CheckForDbUpgrade()
{
var data = _connection.Query<DbVersion>(SQLiteProcedures.GET_DB_VERSION);
if (!data.Any())
{
//Pre-Upgrade database, need upgrading
_logger.Trace("Pre version 0.2 RC database found, performing update..");
ExecuteUpgradeFromVersion("0.1"); //execute 0.2 upgrade scripts onwards.
}
else
{
var installedVersion = new Version(data.First().VersionNumber);
var currentVersion = new Version(AssemblyInfo.ASSEMBLY_VERSION);
if (currentVersion.CompareTo(installedVersion) > 0) //greater than 0 - current version is newer
{
_logger.Trace("Installed Database Version: {0} is older than current version {1}");
ExecuteUpgradeFromVersion(installedVersion.ToString());
}
}
}
private void ExecuteUpgradeFromVersion(string installedVersion)
{
const string PREFIX = "SQLiteRepository.UpgradeScripts.";
var instVers = new Version(installedVersion);
//so we have established that each script for upgrade will be <version>.sql, so now start at lowest version and work up!
var assembly = Assembly.GetExecutingAssembly();
var upgradeScripts = assembly.GetManifestResourceNames()
.Where(x=>x.StartsWith(PREFIX))
.OrderBy(x=>new Version(Path.GetFileNameWithoutExtension(x.Replace(PREFIX, ""))))
.Where(x =>
{
var scriptVersion = new Version(Path.GetFileNameWithoutExtension(x.Replace(PREFIX, ""))).CompareTo(instVers);
return scriptVersion > 0;
}
)
.ToList();
//now have an ordered list of upgrade script files, so execute in order!
foreach (var upgradeScript in upgradeScripts)
{
using (var stream = assembly.GetManifestResourceStream(upgradeScript))
using(var str = new StreamReader(stream))
{
var script = str.ReadToEnd();
_logger.Trace("Executing upgrade script with name: {0}", upgradeScript);
_connection.Execute(script);
}
}
SetDbVersion(AssemblyInfo.ASSEMBLY_VERSION);
}
private void SetDbVersion(string vers)
{
_connection.DeleteAll<DbVersion>();
_connection.Insert(new DbVersion {VersionNumber = vers});
_logger.Trace("Set Database version to: {0}", vers);
}
private DateTime GetLastLogDateTime(TimeLogDb timeLog)
{
if (timeLog != null)
{
return timeLog.SwipeEventDateTime.DateTime;
}
return DateTime.MinValue;
}
private bool GetUserState(LogDirectionDb logDirection)
{
switch (logDirection)
{
case LogDirectionDb.OUT:
return true;
default:
return false;
}
}
private int ConvertSourceToIdentifierId(LogSource logSource)
{
switch (logSource)
{
case LogSource.UI:
return -100;
case LogSource.TRAYAPP:
return -200;
default:
return -10;
}
}
private bool SetUserGroups(int userId, List<Group> groups)
{
var groupIds = GetGroupIds(groups.Select(x => x.Name).ToList());
return SetUserGroups(userId, groupIds);
}
private bool SetUserGroups(int userId, int[] groupIds)
{
//remove the existing user>group associations
_connection.Query<UserGroupJoinDb>("delete from UserGroupJoinDb where UserId_FK = ?", userId);
//add the new group associations.
_connection.InsertAll(groupIds.Select(x => new UserGroupJoinDb { GroupId_FK = x, UserId_FK = userId }));
return true;
}
private int[] GetGroupIds(List<string> groupNames)
{
var ret = new List<int>();
foreach (var g in groupNames)
{
var query = _connection.Query<GroupDb>("select GroupId from GroupDb where GroupName=?", g);
if (!query.Any()) continue;
var id = query.First();
ret.Add(id.GroupId);
}
return ret.ToArray();
}
private List<DailyLogs> GetTimeLogList(int userId, int calendarWeek, int year)
{
var timeLogList = _connection.Query<TimeLogDb>(
SQLiteProcedures.GET_TIMELOGS,
userId, calendarWeek, year);
var timeLogs = timeLogList.Select(x => new TimeLog
{
Id = x.Id,
CalendarWeek = x.CalendarWeek,
Direction = (LogDirection)x.Direction,
IdentifierId = x.IdentifierId,
EventTime = x.SwipeEventDateTime,
UserId = x.UserId_FK,
Year = x.Year
}).OrderBy(x=>x.EventTime.UtcDateTime).ToList();
var dict = new Dictionary<DayOfWeek, DailyLogs>();
var logList = new List<DailyLogs>();
//make sure each day of the week is accounted for in the dictionary.
foreach (DayOfWeek day in Enum.GetValues(typeof(DayOfWeek)))
{
dict.Add(day, new DailyLogs());
}
//add the logs to the respective day of the week.
foreach (var log in timeLogs.OrderBy(x=>x.EventTime))
{
dict[log.EventTime.DayOfWeek].Logs.Add(log);
}
var logGroups = timeLogs.GroupBy(x => x.EventTime.DayOfWeek);
foreach (var group in logGroups)
{
var groupLogs = group.ToList();
var dailyLog = new DailyLogs
{
Logs = groupLogs,
Day = group.Key,
DayOfWeek = group.Key.ToString()
};
dailyLog.DailyTotal = CalculateDailyTotal(dailyLog);
logList.Add(dailyLog);
}
foreach (DayOfWeek day in Enum.GetValues(typeof(DayOfWeek)))
{
if (logList.Any(x => x.Day == day)) continue;
var dailyLog = new DailyLogs { Day = day, DayOfWeek = day.ToString() };
logList.Add(dailyLog);
}
foreach (var dailyCollection in dict)
{
dailyCollection.Value.DailyTotal = CalculateDailyTotal(dailyCollection.Value);
}
return logList.OrderBy(x => ((int)x.Day + 6) % 7).ToList();
}
private double CalculateDailyTotal(DailyLogs dailyLogs)
{
var totalInTime = TimeSpan.FromSeconds(0);
var logs = dailyLogs.Logs.OrderBy(x => x.EventTime.UtcDateTime).ToArray();
var totalCalcMax = IsOdd(logs.Length) ? logs.Length - 1 : logs.Length;
for (int i = 0; i < totalCalcMax; i += 2)
{
totalInTime += (logs[i + 1].EventTime - logs[i].EventTime);
}
return Math.Round(totalInTime.TotalMinutes, 2);
}
/// <summary>
/// determines if the number is an odd or even value
/// </summary>
/// <param name="value">number to determine is odd or even</param>
/// <returns>true - number is odd</returns>
private bool IsOdd(int value)
{
return value % 2 != 0;
}
/// <summary>
/// Get the new direction for the user based on previous entry logs in the system.
/// </summary>
/// <remarks>
/// If the user has not logged in today, the direction will be In.
/// If the user has logged in already today, the direction will be the opposite of the last
/// recorded log direction. ("out" if "in", "in" if "out")
/// </remarks>
/// <param name="userId">Id of the user to get the log direction of.</param>
/// <returns><see cref="LogDirectionDb"/> indicating what direction the new log is.</returns>
private LogDirectionDb GetLogDirection(int userId)
{
var logDirection = LogDirectionDb.UNKNOWN;
if (userId != -1)
{
var lastEntry = GetLastTimeLog(userId);
if (lastEntry != null)
{
// See if the datetime retrieved is yesterday. If yesterday, logDirection = true (in)
if (IsLogDateTimeYesterdayOrOlder(lastEntry.SwipeEventDateTime.DateTime))
{
logDirection = LogDirectionDb.IN;
}
else
{
// we have a time log from today already, so just do the opposite of what we last did!
logDirection = LogDirectionConverter.InvertLogDirectionDb(lastEntry.Direction);
}
}
else
{
//assume its the first then!
logDirection = LogDirectionDb.IN;
}
}
return logDirection;
}
private TimeLogDb GetLastTimeLog(int userId)
{
var lastEntry = _connection.Query<TimeLogDb>(
SQLiteProcedures.GET_LAST_TIMELOG_DIRECTION,
userId);
if (lastEntry.Any())
{
return lastEntry.First();
}
return null;
}
private void UpdateIdentifierLastUsed(DateTimeOffset dt, int cardId)
{
_connection.ExecuteScalar<CardUniqueId>(SQLiteProcedures.UPDATE_CARD_LAST_USED,
dt,
cardId);
}
private List<Identifier> GetAssociatedIdentifiers(int userId)
{
var cards = _connection.Query<CardUniqueId>(
SQLiteProcedures.GET_CARDS_BY_USER_ID,
userId);
var ret = new List<Identifier>();
foreach (var card in cards)
{
ret.Add(new Identifier()
{
UniqueId = card.CardUId,
IsAssociatedToUser = true,
Id = card.Id
});
}
return ret;
}
/// <summary>
/// Get the calendar week of the year according to the ISO8601 standard (starts monday).
/// </summary>
/// <param name="date">the date to get the calendar week of.</param>
/// <returns>the calendar week of the year in integer form (1-52)</returns>
private int GetIso8601CalendarWeek(DateTime date)
{
var day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(date);
if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
{
date = date.AddDays(3);
}
return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek,
DayOfWeek.Monday);
}
/// <summary>
/// Check whether the specified DateTime is from yesterday or older.
/// </summary>
/// <param name="dt">the DateTime object to check is yesterday or older</param>
/// <returns>true - is yesterday or older.</returns>
private bool IsLogDateTimeYesterdayOrOlder(DateTime dt)
{
return dt.Date.CompareTo(DateTime.Today.Date) < 0;
}
private void UpdateExistingLogDirections(TimeLog log)
{
//need to make this generic so that both create and delete will update the log directions.. but ARGH.
//if you want to use this as a delete, you would delete and call this, if you want to create, call this then create.
//should look at how to improve this method so that it will compensate for if the log hasnt been deleted yet, but ott?
var weekLogs = GetTimeLogList(log.UserId, log.CalendarWeek, log.Year);
//Get the same logs of the day that the log has been entered for
var todaysLogs = weekLogs.FirstOrDefault(x => x.Day == log.EventTime.DayOfWeek);
if (todaysLogs != null)
{
//Get the days logs that are after the manually created date
var logs = todaysLogs.Logs.Where(x => x.EventTime.CompareTo(log.EventTime) >= 0).OrderBy(x => x.EventTime).ToList();
//Update each log with the inverse progressively
var currentlogDirection = log.Direction;
for (var i = 0; i < logs.Count; i++)
{
logs[i].Direction = LogDirectionConverter.InvertLogDirection(currentlogDirection);
UpdateLog(logs[i]);
currentlogDirection = logs[i].Direction;
}
}
}
}
}