diff --git a/AppShell.xaml b/AppShell.xaml index b1bb675..90b5da6 100644 --- a/AppShell.xaml +++ b/AppShell.xaml @@ -4,11 +4,22 @@ xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:MauiApp1" + xmlns:views="clr-namespace:MauiApp1.Views" Shell.FlyoutBehavior="Disabled"> - + + + + + + + diff --git a/DB-Manager.csproj b/DB-Manager.csproj index 1a8369d..a9d52a9 100644 --- a/DB-Manager.csproj +++ b/DB-Manager.csproj @@ -28,6 +28,7 @@ 10.0.17763.0 10.0.17763.0 6.5 + en @@ -61,4 +62,19 @@ + + + RequestSpecialists.xaml + + + + + + MSBuild:Compile + + + MSBuild:Compile + + + diff --git a/DatabaseInitialiser.cs b/DatabaseInitialiser.cs index cceb894..4a21a6c 100644 --- a/DatabaseInitialiser.cs +++ b/DatabaseInitialiser.cs @@ -1,6 +1,7 @@ using Microsoft.Data.Sqlite; using System; using System.Collections.Generic; +using System.Xml.Linq; /// /// Initializes a SQLite database by creating the necessary tables. @@ -85,7 +86,9 @@ private static List GetTableCreationCommands() "CREATE TABLE IF NOT EXISTS rota_type (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)", "CREATE TABLE IF NOT EXISTS equipment_type (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)", "CREATE TABLE IF NOT EXISTS organisation_type (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)", - "CREATE TABLE IF NOT EXISTS order_status (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)", + "CREATE TABLE IF NOT EXISTS organisation (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)", + "CREATE TABLE IF NOT EXISTS person (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL, FieldName TEXT NOT NULL)", + "CREATE TABLE IF NOT EXISTS order_status (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)", "CREATE TABLE IF NOT EXISTS resource_types (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)", "CREATE TABLE IF NOT EXISTS room_type (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)", "CREATE TABLE IF NOT EXISTS room_use_type (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)", @@ -98,9 +101,20 @@ private static List GetTableCreationCommands() "CREATE TABLE IF NOT EXISTS assignment_status (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)", "CREATE TABLE IF NOT EXISTS position_status (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)", "CREATE TABLE IF NOT EXISTS role (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)", - "CREATE TABLE IF NOT EXISTS skill (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)", + "CREATE TABLE IF NOT EXISTS skill (Name TEXT NOT NULL PRIMARY KEY)", "CREATE TABLE IF NOT EXISTS team_member (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)", - "CREATE TABLE IF NOT EXISTS partner_agencies (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)" - }; + "CREATE TABLE IF NOT EXISTS partner_agencies (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL)", + "CREATE TABLE IF NOT EXISTS skills_request (Id INTEGER PRIMARY KEY AUTOINCREMENT, skill_name TEXT, " + + "organisation_id INTEGER, request_date DATE, requested_by INTEGER, number_required INTEGER, " + + "start_date DATE, end_date DATE, status TEXT CHECK (status IN ('Pending', 'Approved'))," + + " confirmed_date DATE, FOREIGN KEY (skill_name) REFERENCES skill(Name), " + + "FOREIGN KEY (organisation_id) REFERENCES organisation(Id),FOREIGN KEY (requested_by) REFERENCES person(Id));" + + //TEST Values for Specialist Requests + ,"INSERT OR IGNORE INTO person (Id, Name, FieldName) VALUES (0,'John Doe', 'Healthcare');" + ,"INSERT OR IGNORE INTO organisation (Id, Name) VALUES (0, 'No Organisation'),(2, 'Doctors Without Borders'),(2, 'Care'),(3, 'International Medical Corps');" + ,"INSERT OR IGNORE INTO skill (Name) VALUES ('rescue'),('rebuild Infrastructure'),('mental & emotional support'),('first aid');" + //,"DROP TABLE IF EXISTS skills_request;" + }; } } diff --git a/DatabaseOperations.cs b/DatabaseOperations.cs index 52382a4..8a9ea8b 100644 --- a/DatabaseOperations.cs +++ b/DatabaseOperations.cs @@ -74,24 +74,48 @@ public int GetRecordIdByName(string tableName, string name) command.CommandText = commandText; command.Parameters.AddWithValue("@name", name); - var result = command.ExecuteScalar(); + var result = Convert.ToInt32(command.ExecuteScalar()); - if (result != null && result is int id) + if (result is int id) { return id; } - throw new Exception($"No record with the name '{name}' found in table '{tableName}'."); + throw new Exception($"No record with the name '{name}' found in table '{tableName}'." ); } - /// - /// Updates a record's name in the specified table based on the provided ID. - /// - /// Target table name. - /// ID of the record to update. - /// New name to set for the record. - public void UpdateRecord(string tableName, int id, string newName) + /// + /// Retrieves the name of a record from a specified table based on its ID. + /// + /// The table to search in. + /// The id of the record to search for. + /// The ID of the record if found; otherwise, throws an exception. + public string GetRecordNameById(string tableName, int id) + { + var commandText = $"SELECT Id FROM {tableName} WHERE Id = @Id LIMIT 1"; + + using var command = _connection.CreateCommand(); + command.CommandText = commandText; + command.Parameters.AddWithValue("@Id", id); + + var result = command.ExecuteScalar(); + + if (result != null && result is string name) + { + return name; + } + + throw new Exception($"No record with the name '{id}' found in table '{tableName}'."); + } + + /// + /// Updates a record's name in the specified table based on the provided ID. + /// + /// Target table name. + /// ID of the record to update. + /// New name to set for the record. + public void UpdateRecord(string tableName, int id, string newName) { var commandText = $"UPDATE {tableName} SET Name = @name WHERE Id = @id"; ExecuteNonQuery(commandText, ("@name", newName), ("@id", id)); diff --git a/Models/SkillRequest.cs b/Models/SkillRequest.cs new file mode 100644 index 0000000..31c262f --- /dev/null +++ b/Models/SkillRequest.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MauiApp1.Models +{ + public class SkillRequest + { + public int Id { get; set; } + public string SkillName { get; set; } + public int OrganisationId { get; set; } + public DateTime RequestDate { get; set; } + public int RequestedBy { get; set; } + public int NumberRequired { get; set; } + public DateTime StartDate { get; set; } + public DateTime EndDate { get; set; } + public string Status { get; set; } + public DateTime ConfirmedDate { get; set; } + } +} diff --git a/Services/ISpecialistRequestService.cs b/Services/ISpecialistRequestService.cs new file mode 100644 index 0000000..7b8ec66 --- /dev/null +++ b/Services/ISpecialistRequestService.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MauiApp1.Models; + +namespace MauiApp1.Services +{ + internal interface ISpecialistRequestService + { + /// + /// Inserts a new unapporved Specialist Request in the skills_request table + /// (confirmed_date can not be null so it is set to MinValue aswell as organisation. + /// requested_by is a dummy Value) + /// + /// Required Skill + /// Number of Persons Required + /// Start Date + /// End Date + void AddUnapprovedSkillRequest(string skillName, int numberRequired, + DateTime startDate,DateTime endDate); + + /// + /// Returns a list of SkillRequest objects by Calling a + /// SELECT statement for skills_request + /// + /// A list of SkillRequest objects, created from the database + List GetAllSkillRequests(); + + /// + /// Approve Request by assingning the date of approval, + /// changing the Status to Approved, and Assignig the Corresponding Organisation + /// + /// Id of Request + /// Id of Organisation + void approveSkillRequest(int id, int organisationId); + + void deleteSkillRequestById(int id); + } +} diff --git a/Services/SpecialistRequestService.cs b/Services/SpecialistRequestService.cs new file mode 100644 index 0000000..2a124db --- /dev/null +++ b/Services/SpecialistRequestService.cs @@ -0,0 +1,150 @@ +using Microsoft.Data.Sqlite; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MauiApp1.Models; + +namespace MauiApp1.Services +{ + /// + /// Service to Apply the required SQL Statements to Add new + /// + internal class SpecialistRequestService : ISpecialistRequestService + { + private readonly SqliteConnection _connection; + + /// + /// Creates a new database operation instance, initializing the connection to the SQLite database. + /// + /// The SQLite database connection string. + public SpecialistRequestService(string connectionString) + { + _connection = new SqliteConnection(connectionString); + + try + { + _connection.Open(); + } + catch (Exception ex) + { + throw new Exception("Error establishing database connection.", ex); + } + } + + /// + /// Inserts a new unapporved Specialist Request in the skills_request table + /// (confirmed_date can not be null so it is set to MinValue aswell as organisation. + /// requested_by is a dummy Value) + /// + /// Required Skill + /// Number of Persons Required + /// Start Date + /// End Date + void ISpecialistRequestService.AddUnapprovedSkillRequest(string skillName, int numberRequired, + DateTime startDate, DateTime endDate) + { + var commandText = "INSERT INTO skills_request " + + "(skill_name, organisation_id, request_date, requested_by, number_required, " + + "start_date, end_date, status, confirmed_date) " + + "VALUES " + + "(@skill_name, @organisation_id, @request_date, @requested_by, @number_required, " + + "@start_date, @end_date, @status, @confirmed_date)"; + + using (var command = new SqliteCommand(commandText, _connection)) + { + command.Parameters.AddWithValue("@skill_name", skillName); + command.Parameters.AddWithValue("@organisation_id", 0); + command.Parameters.AddWithValue("@request_date", DateTime.Today); + command.Parameters.AddWithValue("@requested_by", 0); // dummy value + command.Parameters.AddWithValue("@number_required", numberRequired); + command.Parameters.AddWithValue("@start_date", startDate); + command.Parameters.AddWithValue("@end_date", endDate); + command.Parameters.AddWithValue("@status", "Pending"); + command.Parameters.AddWithValue("@confirmed_date", DateTime.MinValue); + + command.ExecuteNonQuery(); + } + } + + /// + /// Approve Request by assingning the date of approval, + /// changing the Status to Approved, and Assignig the Corresponding Organisation + /// + /// Id of Request + /// Id of Organisation + void ISpecialistRequestService.approveSkillRequest(int id, int organisationId) + { + var currentDate = DateTime.Today; + var commandText = "UPDATE skills_request SET confirmed_date = @currentDate," + + " organisation_id = @organisationId, status = 'Approved' WHERE Id = @id"; + + using (var command = new SqliteCommand(commandText, _connection)) + { + command.Parameters.AddWithValue("@currentDate", currentDate); + command.Parameters.AddWithValue("@organisationId", organisationId); + command.Parameters.AddWithValue("@id", id); + + command.ExecuteNonQuery(); + } + } + + /// + /// Returns a list of SkillRequest objects by Calling a + /// SELECT statement for skills_request + /// + /// A list of SkillRequest objects, created from the database + List ISpecialistRequestService.GetAllSkillRequests() + { + var skillRequests = new List(); + var commandText = "SELECT * FROM skills_request"; + + using var command = _connection.CreateCommand(); + command.CommandText = commandText; + + using (var reader = command.ExecuteReader()) + { + while (reader.Read()) + { + SkillRequest skillRequest = CreateSkillRequestFromReader(reader); + skillRequests.Add(skillRequest); + } + } + return skillRequests; + } + + void ISpecialistRequestService.deleteSkillRequestById(int id) + { + var commandText = $"DELETE FROM skills_request WHERE Id = @id"; + using (var command = new SqliteCommand(commandText, _connection)) + { + command.Parameters.AddWithValue("@id", id); + + command.ExecuteNonQuery(); + } + } + /// + /// Creates one SkillRequest object by transfering + /// data from the reader. + /// + /// Reading Database respose + /// + private SkillRequest CreateSkillRequestFromReader(SqliteDataReader reader) + { + return new SkillRequest + { + Id = reader.GetInt32(0), + SkillName = reader.GetString(1), + OrganisationId = reader.GetInt32(2), + RequestDate = reader.GetDateTime(3), + RequestedBy = reader.GetInt32(4), + NumberRequired = reader.GetInt32(5), + StartDate = reader.GetDateTime(6), + EndDate = reader.GetDateTime(7), + Status = reader.GetString(8), + ConfirmedDate = reader.GetDateTime(9) + }; + } + } +} diff --git a/Views/AcceptSpecialistRequests.xaml b/Views/AcceptSpecialistRequests.xaml new file mode 100644 index 0000000..0f734c8 --- /dev/null +++ b/Views/AcceptSpecialistRequests.xaml @@ -0,0 +1,98 @@ + + + + + + +