FlexitimeTracker/DataCenter_Windows/WindowsDataCenter/SQLiteRepository/SQLiteRepository.cs
chris.watts90@outlook.com 0867cbd7a6 implemented the GetTimeLogs methods.
re-referenced TimeLog to TimeLogDB
implemented the LogEventTime method, now logs direction user was going.
also logs the CalendarWeek and Year, returns the Id of the time log entry now too.
2017-02-08 22:22:36 +00:00

395 lines
14 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Interfaces;
using SQLite.Net;
using SQLite.Net.Platform.Win32;
namespace SQLiteRepository
{
public class SQLiteRepository : IRepository
{
private readonly SQLiteConnection _connection;
private string _path = "flexitimedb.db";
public SQLiteRepository()
{
_connection = new SQLiteConnection(new SQLitePlatformWin32(), _path);
_connection.CreateTable<CardUniqueId>();
_connection.CreateTable<UserIdentity>();
_connection.CreateTable<TimeLogDB>();
}
public UserList GetUsers()
{
var ret = new UserList();
var users = _connection.Query<UserIdentity>(SQLiteProcedures.GET_ALL_USERS);
if (!users.Any())
{
ret.PageNumber = 1;
ret.PageSize = 20;
return ret;
}
foreach (var user in users)
{
var userObj = ChangeToUserObject(user);
var cards = _connection.Query<CardUniqueId>(
SQLiteProcedures.GET_CARDS_BY_USER_ID,
user.Id);
foreach (var card in cards)
{
userObj.AssociatedIdentifiers.Add(new Identifier()
{
UniqueId = card.CardUId,
IsAssociatedToUser = true,
Id = card.Id
});
}
ret.Users.Add(userObj);
}
ret.PageSize = 20;
ret.PageNumber = 1;
return ret;
}
public UserList Search(string searchParam)
{
var ret = new UserList();
searchParam = string.Format("%{0}%", searchParam);
var users = _connection.Query<UserIdentity>(
SQLiteProcedures.SEARCH_USER_LIST,
searchParam, searchParam);
if (!users.Any())
{
ret.PageNumber = 1;
ret.PageSize = 20;
return ret;
}
foreach (var user in users)
{
var userObj = ChangeToUserObject(user);
var cards = _connection.Query<CardUniqueId>(
SQLiteProcedures.GET_CARDS_BY_USER_ID,
user.Id);
foreach (var card in cards)
{
userObj.AssociatedIdentifiers.Add(new Identifier()
{
UniqueId = card.CardUId,
IsAssociatedToUser = true,
Id = card.Id
});
}
ret.Users.Add(userObj);
}
ret.PageSize = 20;
ret.PageNumber = 1;
return ret;
}
public User GetUser(int id)
{
var ret = new User();
var users = _connection.Query<UserIdentity>(
SQLiteProcedures.GET_USER_BY_ID,
id);
if (!users.Any()) return ret;
var user = users.First();
ret = ChangeToUserObject(user);
var cards = _connection.Query<CardUniqueId>(
SQLiteProcedures.GET_CARDS_BY_USER_ID,
user.Id);
foreach (var card in cards)
{
ret.AssociatedIdentifiers.Add(new Identifier { UniqueId = card.CardUId, IsAssociatedToUser = true, Id = card.Id});
}
return ret;
}
public TimeLogList GetTimeLogs(int userId)
{
var ret = new TimeLogList();
//get this calendar week;
var now = DateTime.UtcNow;
var calendarWeek = GetIso8601CalendarWeek(now);
ret.CalendarWeek = calendarWeek;
ret.TimeLogs = GetTimeLogList(userId, calendarWeek, now.Year);
return ret;
}
public TimeLogList GetTimeLogs(int userId, int calendarWeek)
{
var ret = new TimeLogList();
var now = DateTime.UtcNow;
ret.CalendarWeek = calendarWeek;
ret.TimeLogs = GetTimeLogList(userId, calendarWeek, now.Year);
return ret;
}
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(new Identifier
{
Id = card.Id,
IsAssociatedToUser = card.UserId_FK != Constants.UNASSIGNED_CARD_USER_ID,
UniqueId = card.CardUId
});
}
return ret;
}
//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)
{
//if(user.UserId <=0) return OperationResponse.FAILED;
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(x => new Identifier {Id = x.Id, IsAssociatedToUser = true, UniqueId = x.CardUId});
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 = new CardUniqueId { CardUId = card.UniqueId, UserId_FK = -1 };
_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>(
"update UserIdentity set FirstName=?, LastName=?, HoursPerWeek=?,IsContractor=? where Id=?",
user.FirstName,
user.LastName,
user.HoursPerWeek,
user.IsContractor,
user.UserId
);
userId = user.UserId;
}
else
{
var userInsert = new UserIdentity
{
FirstName = user.FirstName,
LastName = user.LastName,
HoursPerWeek = user.HoursPerWeek,
IsContractor = user.IsContractor
};
_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,
-1, card);
}
#endregion
userIdResult = userId;
return ret;
}
public OperationResponse LogEventTime(Identifier identifier, out int logId)
{
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);
}
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 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
//TODO: Handle When the identifier is assigned to a user (identifier has -1)
//when identifier not assigned to user, just store it anyway and carry on, can update later.
var timeLog = new TimeLogDB
{
SwipeEventDateTime = DateTime.UtcNow,
UserId_FK = ident.UserId_FK,
IdentifierId = ident.Id,
Direction = logDirection,
Year = year,
CalendarWeek=calendarWeek
};
_connection.Insert(timeLog);
logId = timeLog.Id;
return OperationResponse.SUCCESS;
}
private List<TimeLog> GetTimeLogList(int userId, int calendarWeek, int year)
{
List<TimeLog> ret;
var timeLogList = _connection.Query<TimeLogDB>(
SQLiteProcedures.GET_TIMELOGS,
userId, calendarWeek, year);
ret= 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
}).ToList();
return ret;
}
private LogDirectionDB GetLogDirection(int userId)
{
var logDirection = LogDirectionDB.UNKNOWN;
if (userId != -1)
{
var lastEntry = _connection.Query<TimeLogDB>(
SQLiteProcedures.GET_LAST_TIMELOG_DIRECTION,
userId);
if (lastEntry.Any())
{
var lastLog = lastEntry.First();
// See if the datetime retrieved is yesterday. If yesterday, logDirection = true (in)
if (IsLogDateTimeYesterdayOrOlder(lastLog.SwipeEventDateTime.DateTime))
{
logDirection = LogDirectionDB.IN;
}
else
{
// we have a time log from today already, so just do the opposite of what we last did!
if (lastLog.Direction == LogDirectionDB.IN)
logDirection = LogDirectionDB.OUT;
else if (lastLog.Direction == LogDirectionDB.OUT)
logDirection = LogDirectionDB.IN;
}
}
else
{
//assume its the first then!
logDirection = LogDirectionDB.IN;
}
}
return logDirection;
}
/// <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);
}
private bool IsLogDateTimeYesterdayOrOlder(DateTime dt)
{
return dt.Date.CompareTo(DateTime.Today.Date) < 0;
}
private User ChangeToUserObject(UserIdentity user)
{
return new User
{
UserId = user.Id,
FirstName = user.FirstName,
LastName = user.LastName,
HoursPerWeek = user.HoursPerWeek,
IsContractor = user.IsContractor
};
}
}
}