FlexitimeTracker/DataCenter_Windows/WindowsDataCenter/SQLiteRepository/SQLiteRepository.cs
Chris.Watts90@outlook.com 19b718a946 changed IRepository to accept a DateTime for the arg, instead of an int for calendar week/year.
added SelectedDate to the TimeLog object.
changed the timelog controller to accept a datetime as an arg, instead of the previous calendarweek/year args.
This kills two birds with one arg.
Changed the goToTimeLogs function to accept an args object to allow passing of datetime SelectedDate parameter.
removed console.logs to tidy code a little.
corrected some "undefined" parameter bugs/errors.
#5
2017-02-10 12:07:02 +00:00

394 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, DateTime selectedDate)
{
var ret = new TimeLogList {SelectedDate = selectedDate};
var calendarWeek = GetIso8601CalendarWeek(selectedDate);
ret.CalendarWeek = calendarWeek;
ret.TimeLogs = GetTimeLogList(userId, calendarWeek, selectedDate.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)
{
var timeLogList = _connection.Query<TimeLogDb>(
SQLiteProcedures.GET_TIMELOGS,
userId, calendarWeek, year);
var 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
};
}
}
}