diff --git a/DotnetFoundation/DotnetFoundation.Api/Controllers/TaskController.cs b/DotnetFoundation/DotnetFoundation.Api/Controllers/TaskController.cs
new file mode 100644
index 0000000..021c8d3
--- /dev/null
+++ b/DotnetFoundation/DotnetFoundation.Api/Controllers/TaskController.cs
@@ -0,0 +1,123 @@
+using DotnetFoundation.Application.Interfaces.Services;
+using DotnetFoundation.Application.Models.Common;
+using DotnetFoundation.Application.Models.DTOs.TaskDetailsDTO;
+using DotnetFoundation.Application.Models.Enums;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace DotnetFoundation.Api.Controllers;
+
+[ApiController]
+[Route("api/tasks")]
+public class TaskController : ControllerBase
+{
+ private readonly ITaskDetailsService _taskDetailsService;
+ public TaskController(ITaskDetailsService TaskDetailsService)
+ {
+ _taskDetailsService = TaskDetailsService;
+ }
+
+ ///
+ /// Get all tasks.
+ ///
+ [HttpGet]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status500InternalServerError)]
+ public async Task>>> GetAllTasksAsync()
+ {
+ BaseResponse> response = new(ResponseStatus.Fail);
+
+ response.Data = await _taskDetailsService.GetAllTasksAsync().ConfigureAwait(false);
+ response.Status = ResponseStatus.Success;
+
+ return Ok(response);
+ }
+
+ ///
+ /// Get all active tasks.
+ ///
+ [HttpGet("active")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status500InternalServerError)]
+ public async Task>>> GetActiveTasksAsync()
+ {
+ BaseResponse> response = new(ResponseStatus.Fail);
+
+ response.Data = await _taskDetailsService.GetActiveTasksAsync().ConfigureAwait(false);
+ response.Status = ResponseStatus.Success;
+
+ return Ok(response);
+ }
+
+ ///
+ /// Get task details by Id.
+ ///
+ /// Id of task record
+ [HttpGet("{taskId}")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ [ProducesResponseType(StatusCodes.Status500InternalServerError)]
+ public async Task>> GetTaskByIdAsync(int taskId)
+ {
+ BaseResponse response = new(ResponseStatus.Fail);
+
+ response.Data = await _taskDetailsService.GetTaskByIdAsync(taskId).ConfigureAwait(false);
+ response.Status = ResponseStatus.Success;
+
+ return Ok(response);
+ }
+
+ ///
+ /// Add new task.
+ ///
+ /// Role request details
+ [HttpPost]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(StatusCodes.Status500InternalServerError)]
+ public async Task>> InsertTaskAsync(TaskDetailsRequest detailRequest)
+ {
+ BaseResponse response = new(ResponseStatus.Fail);
+
+ response.Data = await _taskDetailsService.InsertTaskAsync(detailRequest).ConfigureAwait(false);
+ response.Status = ResponseStatus.Success;
+
+ return Ok(response);
+ }
+
+ ///
+ /// Update details of a task when the Id is passed.
+ ///
+ /// Id of task record
+ /// Modified details for task record
+ [HttpPut("{taskId}")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status500InternalServerError)]
+ public async Task>> UpdateTaskAsync(int taskId, TaskDetailsRequest modifiedDetails)
+ {
+ BaseResponse response = new(ResponseStatus.Fail);
+
+ response.Data = await _taskDetailsService.UpdateTaskAsync(taskId, modifiedDetails).ConfigureAwait(false);
+ response.Status = ResponseStatus.Success;
+
+ return Ok(response);
+ }
+
+ ///
+ /// Change status of task to inactive.
+ ///
+ /// Id of task record
+ [HttpDelete("{taskId}")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status500InternalServerError)]
+ public async Task>> InactiveTaskAsync(int taskId)
+ {
+ BaseResponse response = new(ResponseStatus.Fail);
+
+ response.Data = await _taskDetailsService.InactiveTaskAsync(taskId).ConfigureAwait(false);
+ response.Status = ResponseStatus.Success;
+
+ return Ok(response);
+ }
+}
diff --git a/DotnetFoundation/DotnetFoundation.Api/Helpers/AutoMappingProfile.cs b/DotnetFoundation/DotnetFoundation.Api/Helpers/AutoMappingProfile.cs
index b9484cc..d2117d9 100644
--- a/DotnetFoundation/DotnetFoundation.Api/Helpers/AutoMappingProfile.cs
+++ b/DotnetFoundation/DotnetFoundation.Api/Helpers/AutoMappingProfile.cs
@@ -1,5 +1,6 @@
using AutoMapper;
using DotnetFoundation.Application.Models.DTOs.UserDTO;
+using DotnetFoundation.Application.Models.DTOs.TaskDetailsDTO;
using DotnetFoundation.Domain.Entities;
namespace DotnetFoundation.Api.Helpers;
@@ -9,5 +10,6 @@ public class AutoMappingProfile : Profile
public AutoMappingProfile()
{
CreateMap();
+ CreateMap();
}
}
diff --git a/DotnetFoundation/DotnetFoundation.Application/Interfaces/Persistence/ITaskDetailsRepository.cs b/DotnetFoundation/DotnetFoundation.Application/Interfaces/Persistence/ITaskDetailsRepository.cs
new file mode 100644
index 0000000..58fdc0c
--- /dev/null
+++ b/DotnetFoundation/DotnetFoundation.Application/Interfaces/Persistence/ITaskDetailsRepository.cs
@@ -0,0 +1,17 @@
+using DotnetFoundation.Application.Models.DTOs.TaskDetailsDTO;
+using DotnetFoundation.Domain.Entities;
+
+namespace DotnetFoundation.Application.Interfaces.Persistence;
+
+///
+/// Represents the repository interface for handling task related operations.
+///
+public interface ITaskDetailsRepository
+{
+ public Task> GetAllTasksAsync();
+ public Task> GetActiveTasksAsync();
+ public Task GetTaskByIdAsync(int id);
+ public Task InsertTaskAsync(TaskDetails taskDetails);
+ public Task UpdateTaskAsync(TaskDetailsRequest modifiedDetails, TaskDetails existingDetails);
+ public Task InactiveTaskAsync(TaskDetails existingDetails);
+}
diff --git a/DotnetFoundation/DotnetFoundation.Application/Interfaces/Services/ITaskDetailsService.cs b/DotnetFoundation/DotnetFoundation.Application/Interfaces/Services/ITaskDetailsService.cs
new file mode 100644
index 0000000..b6fb6ff
--- /dev/null
+++ b/DotnetFoundation/DotnetFoundation.Application/Interfaces/Services/ITaskDetailsService.cs
@@ -0,0 +1,16 @@
+using DotnetFoundation.Application.Models.DTOs.TaskDetailsDTO;
+
+namespace DotnetFoundation.Application.Interfaces.Services;
+
+///
+/// Provides functionality for task related operations.
+///
+public interface ITaskDetailsService
+{
+ public Task> GetAllTasksAsync();
+ public Task> GetActiveTasksAsync();
+ public Task GetTaskByIdAsync(int id);
+ public Task InsertTaskAsync(TaskDetailsRequest request);
+ public Task UpdateTaskAsync(int id, TaskDetailsRequest modifiedDetails);
+ public Task InactiveTaskAsync(int id);
+}
\ No newline at end of file
diff --git a/DotnetFoundation/DotnetFoundation.Application/Interfaces/Services/IUsersService.cs b/DotnetFoundation/DotnetFoundation.Application/Interfaces/Services/IUsersService.cs
index 10d9a37..1edb0a7 100644
--- a/DotnetFoundation/DotnetFoundation.Application/Interfaces/Services/IUsersService.cs
+++ b/DotnetFoundation/DotnetFoundation.Application/Interfaces/Services/IUsersService.cs
@@ -1,5 +1,6 @@
using DotnetFoundation.Application.Models.DTOs.UserDTO;
using DotnetFoundation.Domain.Enums;
+
namespace DotnetFoundation.Application.Interfaces.Services;
public interface IUserService
diff --git a/DotnetFoundation/DotnetFoundation.Application/Models/DTOs/TaskDetailsDTO/TaskDetailsRequest.cs b/DotnetFoundation/DotnetFoundation.Application/Models/DTOs/TaskDetailsDTO/TaskDetailsRequest.cs
new file mode 100644
index 0000000..ac8a60f
--- /dev/null
+++ b/DotnetFoundation/DotnetFoundation.Application/Models/DTOs/TaskDetailsDTO/TaskDetailsRequest.cs
@@ -0,0 +1,27 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace DotnetFoundation.Application.Models.DTOs.TaskDetailsDTO;
+
+public record TaskDetailsRequest
+{
+ ///
+ /// Gets the Description of the task.
+ ///
+ [Required(ErrorMessage = "Description is required")]
+ public string Description { get; init; } = string.Empty;
+ ///
+ /// Gets the Budgeted Hours of the task.
+ ///
+ [Required(ErrorMessage = "BudgetedHours is required")]
+ [Range(0, int.MaxValue, ErrorMessage = "BudgetedHours should be in range of 0 to int.Maxvalue")]
+ public int BudgetedHours { get; init; }
+ ///
+ /// Gets the user Id of the user the task is assigned to.
+ ///
+ [Required(ErrorMessage = "AssignedTo is required")]
+ public int AssignedTo { get; init; }
+ ///
+ /// Gets the Category of the task.
+ ///
+ public string? Category { get; init; }
+}
diff --git a/DotnetFoundation/DotnetFoundation.Application/Models/DTOs/TaskDetailsDTO/TaskDetailsResponse.cs b/DotnetFoundation/DotnetFoundation.Application/Models/DTOs/TaskDetailsDTO/TaskDetailsResponse.cs
new file mode 100644
index 0000000..79623db
--- /dev/null
+++ b/DotnetFoundation/DotnetFoundation.Application/Models/DTOs/TaskDetailsDTO/TaskDetailsResponse.cs
@@ -0,0 +1,20 @@
+using DotnetFoundation.Domain.Enums;
+
+namespace DotnetFoundation.Application.Models.DTOs.TaskDetailsDTO;
+
+///
+/// Represents the response for authentication-related actions.
+///
+public record TaskDetailsResponse
+{
+ public int Id { get; init; }
+ public required string Description { get; init; }
+ public int BudgetedHours { get; init; }
+ public int AssignedTo { get; init; }
+ public string? Category { get; init; }
+ public Status Status { get; init; }
+ public DateTime CreatedOn { get; init; }
+ public int CreatedBy { get; init; }
+ public DateTime ModifiedOn { get; init; }
+ public int ModifiedBy { get; init; }
+}
\ No newline at end of file
diff --git a/DotnetFoundation/DotnetFoundation.Domain/Entities/TaskDetails.cs b/DotnetFoundation/DotnetFoundation.Domain/Entities/TaskDetails.cs
new file mode 100644
index 0000000..9828efb
--- /dev/null
+++ b/DotnetFoundation/DotnetFoundation.Domain/Entities/TaskDetails.cs
@@ -0,0 +1,11 @@
+using DotnetFoundation.Domain.Common;
+
+namespace DotnetFoundation.Domain.Entities;
+
+public class TaskDetails : BaseEntity
+{
+ public string Description { get; set; } = null!;
+ public int BudgetedHours { get; set; }
+ public int AssignedTo { get; set; }
+ public string? Category { get; set; }
+}
\ No newline at end of file
diff --git a/DotnetFoundation/DotnetFoundation.Infrastructure/DependencyInjection.cs b/DotnetFoundation/DotnetFoundation.Infrastructure/DependencyInjection.cs
index 835188b..172cf98 100644
--- a/DotnetFoundation/DotnetFoundation.Infrastructure/DependencyInjection.cs
+++ b/DotnetFoundation/DotnetFoundation.Infrastructure/DependencyInjection.cs
@@ -1,5 +1,6 @@
using DotnetFoundation.Application.Interfaces.Integrations;
using DotnetFoundation.Application.Interfaces.Persistence;
+using DotnetFoundation.Application.Interfaces.Services;
using DotnetFoundation.Infrastructure.Identity;
using DotnetFoundation.Infrastructure.Integrations;
using DotnetFoundation.Infrastructure.Persistence;
@@ -73,7 +74,7 @@ public static IServiceCollection AddInfrastructure(this IServiceCollection servi
// Configure service scope for repositories
services.AddScoped();
services.AddScoped();
-
+ services.AddScoped();
services.AddHttpClient();
return services;
diff --git a/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20240228094549_CreateTasks.Designer.cs b/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20240228094549_CreateTasks.Designer.cs
new file mode 100644
index 0000000..742fe58
--- /dev/null
+++ b/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20240228094549_CreateTasks.Designer.cs
@@ -0,0 +1,363 @@
+//
+using System;
+using DotnetFoundation.Infrastructure;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace DotnetFoundation.Infrastructure.Migrations
+{
+ [DbContext(typeof(SqlDatabaseContext))]
+ [Migration("20240228094549_CreateTasks")]
+ partial class CreateTasks
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.2")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ modelBuilder.Entity("DotnetFoundation.Domain.Entities.TaskDetails", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("AssignedTo")
+ .HasColumnType("int");
+
+ b.Property("BudgetedHours")
+ .HasColumnType("int");
+
+ b.Property("Category")
+ .HasColumnType("longtext");
+
+ b.Property("CreatedBy")
+ .HasColumnType("int");
+
+ b.Property("CreatedOn")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("ModifiedBy")
+ .HasColumnType("int");
+
+ b.Property("ModifiedOn")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Status")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("tasks", (string)null);
+ });
+
+ modelBuilder.Entity("DotnetFoundation.Infrastructure.Identity.ApplicationUser", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("CreatedBy")
+ .HasColumnType("int");
+
+ b.Property("CreatedOn")
+ .HasColumnType("datetime(6)");
+
+ b.Property("FirstName")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("IdentityApplicationUserId")
+ .HasColumnType("varchar(255)");
+
+ b.Property("LastName")
+ .HasColumnType("longtext");
+
+ b.Property("ModifiedBy")
+ .HasColumnType("int");
+
+ b.Property("ModifiedOn")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Status")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("IdentityApplicationUserId")
+ .IsUnique();
+
+ b.ToTable("users", (string)null);
+ });
+
+ modelBuilder.Entity("DotnetFoundation.Infrastructure.Identity.IdentityApplicationUser", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("AccessFailedCount")
+ .HasColumnType("int");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnType("longtext");
+
+ b.Property("Email")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("EmailConfirmed")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LockoutEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LockoutEnd")
+ .HasColumnType("datetime(6)");
+
+ b.Property("NormalizedEmail")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("NormalizedUserName")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("PasswordHash")
+ .HasColumnType("longtext");
+
+ b.Property("PhoneNumber")
+ .HasColumnType("longtext");
+
+ b.Property("PhoneNumberConfirmed")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("SecurityStamp")
+ .HasColumnType("longtext");
+
+ b.Property("TwoFactorEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UserName")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedEmail")
+ .HasDatabaseName("EmailIndex");
+
+ b.HasIndex("NormalizedUserName")
+ .IsUnique()
+ .HasDatabaseName("UserNameIndex");
+
+ b.ToTable("AspNetUsers", (string)null);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnType("longtext");
+
+ b.Property("Name")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("NormalizedName")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedName")
+ .IsUnique()
+ .HasDatabaseName("RoleNameIndex");
+
+ b.ToTable("AspNetRoles", (string)null);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("ClaimType")
+ .HasColumnType("longtext");
+
+ b.Property("ClaimValue")
+ .HasColumnType("longtext");
+
+ b.Property("RoleId")
+ .IsRequired()
+ .HasColumnType("varchar(255)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AspNetRoleClaims", (string)null);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("ClaimType")
+ .HasColumnType("longtext");
+
+ b.Property("ClaimValue")
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .IsRequired()
+ .HasColumnType("varchar(255)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AspNetUserClaims", (string)null);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
+ {
+ b.Property("LoginProvider")
+ .HasColumnType("varchar(255)");
+
+ b.Property("ProviderKey")
+ .HasColumnType("varchar(255)");
+
+ b.Property("ProviderDisplayName")
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .IsRequired()
+ .HasColumnType("varchar(255)");
+
+ b.HasKey("LoginProvider", "ProviderKey");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AspNetUserLogins", (string)null);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("varchar(255)");
+
+ b.Property("RoleId")
+ .HasColumnType("varchar(255)");
+
+ b.HasKey("UserId", "RoleId");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AspNetUserRoles", (string)null);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("varchar(255)");
+
+ b.Property("LoginProvider")
+ .HasColumnType("varchar(255)");
+
+ b.Property("Name")
+ .HasColumnType("varchar(255)");
+
+ b.Property("Value")
+ .HasColumnType("longtext");
+
+ b.HasKey("UserId", "LoginProvider", "Name");
+
+ b.ToTable("AspNetUserTokens", (string)null);
+ });
+
+ modelBuilder.Entity("DotnetFoundation.Infrastructure.Identity.ApplicationUser", b =>
+ {
+ b.HasOne("DotnetFoundation.Infrastructure.Identity.IdentityApplicationUser", "IdentityApplicationUser")
+ .WithOne("ApplicationUser")
+ .HasForeignKey("DotnetFoundation.Infrastructure.Identity.ApplicationUser", "IdentityApplicationUserId");
+
+ b.Navigation("IdentityApplicationUser");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
+ {
+ b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
+ .WithMany()
+ .HasForeignKey("RoleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
+ {
+ b.HasOne("DotnetFoundation.Infrastructure.Identity.IdentityApplicationUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
+ {
+ b.HasOne("DotnetFoundation.Infrastructure.Identity.IdentityApplicationUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b =>
+ {
+ b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
+ .WithMany()
+ .HasForeignKey("RoleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("DotnetFoundation.Infrastructure.Identity.IdentityApplicationUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
+ {
+ b.HasOne("DotnetFoundation.Infrastructure.Identity.IdentityApplicationUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("DotnetFoundation.Infrastructure.Identity.IdentityApplicationUser", b =>
+ {
+ b.Navigation("ApplicationUser")
+ .IsRequired();
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20240228094549_CreateTasks.cs b/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20240228094549_CreateTasks.cs
new file mode 100644
index 0000000..bd38a18
--- /dev/null
+++ b/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20240228094549_CreateTasks.cs
@@ -0,0 +1,47 @@
+using System;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace DotnetFoundation.Infrastructure.Migrations
+{
+ ///
+ public partial class CreateTasks : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "tasks",
+ columns: table => new
+ {
+ Id = table.Column(type: "int", nullable: false)
+ .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
+ Description = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ BudgetedHours = table.Column(type: "int", nullable: false),
+ AssignedTo = table.Column(type: "int", nullable: false),
+ Category = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ CreatedOn = table.Column(type: "datetime(6)", nullable: false),
+ CreatedBy = table.Column(type: "int", nullable: false),
+ ModifiedOn = table.Column(type: "datetime(6)", nullable: false),
+ ModifiedBy = table.Column(type: "int", nullable: false),
+ Status = table.Column(type: "int", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_tasks", x => x.Id);
+ })
+ .Annotation("MySql:CharSet", "utf8mb4");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "tasks");
+ }
+ }
+}
diff --git a/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20240229050021_IndexingForTasks.Designer.cs b/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20240229050021_IndexingForTasks.Designer.cs
new file mode 100644
index 0000000..8c11058
--- /dev/null
+++ b/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20240229050021_IndexingForTasks.Designer.cs
@@ -0,0 +1,377 @@
+//
+using System;
+using DotnetFoundation.Infrastructure;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace DotnetFoundation.Infrastructure.Migrations
+{
+ [DbContext(typeof(SqlDatabaseContext))]
+ [Migration("20240229050021_IndexingForTasks")]
+ partial class IndexingForTasks
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.2")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ modelBuilder.Entity("DotnetFoundation.Domain.Entities.TaskDetails", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("AssignedTo")
+ .HasColumnType("int");
+
+ b.Property("BudgetedHours")
+ .HasColumnType("int");
+
+ b.Property("Category")
+ .HasColumnType("longtext");
+
+ b.Property("CreatedBy")
+ .HasColumnType("int");
+
+ b.Property("CreatedOn")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("ModifiedBy")
+ .HasColumnType("int");
+
+ b.Property("ModifiedOn")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Status")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AssignedTo");
+
+ b.HasIndex("Status");
+
+ b.ToTable("tasks", (string)null);
+ });
+
+ modelBuilder.Entity("DotnetFoundation.Infrastructure.Identity.ApplicationUser", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Country")
+ .HasColumnType("longtext");
+
+ b.Property("CreatedBy")
+ .HasColumnType("int");
+
+ b.Property("CreatedOn")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("FirstName")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("IdentityApplicationUserId")
+ .HasColumnType("varchar(255)");
+
+ b.Property("LastName")
+ .HasColumnType("longtext");
+
+ b.Property("ModifiedBy")
+ .HasColumnType("int");
+
+ b.Property("ModifiedOn")
+ .HasColumnType("datetime(6)");
+
+ b.Property("PhoneNumber")
+ .HasColumnType("longtext");
+
+ b.Property("Status")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("IdentityApplicationUserId")
+ .IsUnique();
+
+ b.ToTable("users", (string)null);
+ });
+
+ modelBuilder.Entity("DotnetFoundation.Infrastructure.Identity.IdentityApplicationUser", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("AccessFailedCount")
+ .HasColumnType("int");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnType("longtext");
+
+ b.Property("Email")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("EmailConfirmed")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LockoutEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LockoutEnd")
+ .HasColumnType("datetime(6)");
+
+ b.Property("NormalizedEmail")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("NormalizedUserName")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("PasswordHash")
+ .HasColumnType("longtext");
+
+ b.Property("PhoneNumber")
+ .HasColumnType("longtext");
+
+ b.Property("PhoneNumberConfirmed")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("SecurityStamp")
+ .HasColumnType("longtext");
+
+ b.Property("TwoFactorEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UserName")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedEmail")
+ .HasDatabaseName("EmailIndex");
+
+ b.HasIndex("NormalizedUserName")
+ .IsUnique()
+ .HasDatabaseName("UserNameIndex");
+
+ b.ToTable("AspNetUsers", (string)null);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnType("longtext");
+
+ b.Property("Name")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("NormalizedName")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedName")
+ .IsUnique()
+ .HasDatabaseName("RoleNameIndex");
+
+ b.ToTable("AspNetRoles", (string)null);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("ClaimType")
+ .HasColumnType("longtext");
+
+ b.Property("ClaimValue")
+ .HasColumnType("longtext");
+
+ b.Property("RoleId")
+ .IsRequired()
+ .HasColumnType("varchar(255)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AspNetRoleClaims", (string)null);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("ClaimType")
+ .HasColumnType("longtext");
+
+ b.Property("ClaimValue")
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .IsRequired()
+ .HasColumnType("varchar(255)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AspNetUserClaims", (string)null);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
+ {
+ b.Property("LoginProvider")
+ .HasColumnType("varchar(255)");
+
+ b.Property("ProviderKey")
+ .HasColumnType("varchar(255)");
+
+ b.Property("ProviderDisplayName")
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .IsRequired()
+ .HasColumnType("varchar(255)");
+
+ b.HasKey("LoginProvider", "ProviderKey");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AspNetUserLogins", (string)null);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("varchar(255)");
+
+ b.Property("RoleId")
+ .HasColumnType("varchar(255)");
+
+ b.HasKey("UserId", "RoleId");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AspNetUserRoles", (string)null);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("varchar(255)");
+
+ b.Property("LoginProvider")
+ .HasColumnType("varchar(255)");
+
+ b.Property("Name")
+ .HasColumnType("varchar(255)");
+
+ b.Property("Value")
+ .HasColumnType("longtext");
+
+ b.HasKey("UserId", "LoginProvider", "Name");
+
+ b.ToTable("AspNetUserTokens", (string)null);
+ });
+
+ modelBuilder.Entity("DotnetFoundation.Infrastructure.Identity.ApplicationUser", b =>
+ {
+ b.HasOne("DotnetFoundation.Infrastructure.Identity.IdentityApplicationUser", "IdentityApplicationUser")
+ .WithOne("ApplicationUser")
+ .HasForeignKey("DotnetFoundation.Infrastructure.Identity.ApplicationUser", "IdentityApplicationUserId");
+
+ b.Navigation("IdentityApplicationUser");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
+ {
+ b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
+ .WithMany()
+ .HasForeignKey("RoleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
+ {
+ b.HasOne("DotnetFoundation.Infrastructure.Identity.IdentityApplicationUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
+ {
+ b.HasOne("DotnetFoundation.Infrastructure.Identity.IdentityApplicationUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b =>
+ {
+ b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
+ .WithMany()
+ .HasForeignKey("RoleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("DotnetFoundation.Infrastructure.Identity.IdentityApplicationUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
+ {
+ b.HasOne("DotnetFoundation.Infrastructure.Identity.IdentityApplicationUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("DotnetFoundation.Infrastructure.Identity.IdentityApplicationUser", b =>
+ {
+ b.Navigation("ApplicationUser")
+ .IsRequired();
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20240229050021_IndexingForTasks.cs b/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20240229050021_IndexingForTasks.cs
new file mode 100644
index 0000000..abaa80b
--- /dev/null
+++ b/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20240229050021_IndexingForTasks.cs
@@ -0,0 +1,36 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace DotnetFoundation.Infrastructure.Migrations
+{
+ ///
+ public partial class IndexingForTasks : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateIndex(
+ name: "IX_tasks_AssignedTo",
+ table: "tasks",
+ column: "AssignedTo");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_tasks_Status",
+ table: "tasks",
+ column: "Status");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropIndex(
+ name: "IX_tasks_AssignedTo",
+ table: "tasks");
+
+ migrationBuilder.DropIndex(
+ name: "IX_tasks_Status",
+ table: "tasks");
+ }
+ }
+}
diff --git a/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/SqlDatabaseContextModelSnapshot.cs b/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/SqlDatabaseContextModelSnapshot.cs
index f785d82..e422436 100644
--- a/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/SqlDatabaseContextModelSnapshot.cs
+++ b/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/SqlDatabaseContextModelSnapshot.cs
@@ -19,6 +19,49 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasAnnotation("ProductVersion", "8.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
+ modelBuilder.Entity("DotnetFoundation.Domain.Entities.TaskDetails", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("AssignedTo")
+ .HasColumnType("int");
+
+ b.Property("BudgetedHours")
+ .HasColumnType("int");
+
+ b.Property("Category")
+ .HasColumnType("longtext");
+
+ b.Property("CreatedBy")
+ .HasColumnType("int");
+
+ b.Property("CreatedOn")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("ModifiedBy")
+ .HasColumnType("int");
+
+ b.Property("ModifiedOn")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Status")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AssignedTo");
+
+ b.HasIndex("Status");
+
+ b.ToTable("tasks", (string)null);
+ });
+
modelBuilder.Entity("DotnetFoundation.Infrastructure.Identity.ApplicationUser", b =>
{
b.Property("Id")
@@ -35,6 +78,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasColumnType("datetime(6)");
b.Property("Email")
+ .IsRequired()
.HasColumnType("longtext");
b.Property("FirstName")
diff --git a/DotnetFoundation/DotnetFoundation.Infrastructure/Persistence/TaskRepository.cs b/DotnetFoundation/DotnetFoundation.Infrastructure/Persistence/TaskRepository.cs
new file mode 100644
index 0000000..f5e336c
--- /dev/null
+++ b/DotnetFoundation/DotnetFoundation.Infrastructure/Persistence/TaskRepository.cs
@@ -0,0 +1,67 @@
+using DotnetFoundation.Application.Models.DTOs.TaskDetailsDTO;
+using DotnetFoundation.Application.Interfaces.Persistence;
+using DotnetFoundation.Domain.Entities;
+using Microsoft.EntityFrameworkCore;
+using DotnetFoundation.Domain.Enums;
+
+namespace DotnetFoundation.Infrastructure.Persistence;
+
+public class TaskDetailsRepository : ITaskDetailsRepository
+{
+ private readonly SqlDatabaseContext _dbContext;
+ public TaskDetailsRepository(SqlDatabaseContext sqlDatabaseContext)
+ {
+ _dbContext = sqlDatabaseContext;
+ }
+
+ public async Task> GetAllTasksAsync()
+ {
+ List taskObj = await _dbContext.TaskDetails.ToListAsync().ConfigureAwait(false);
+ return taskObj;
+ }
+
+ public async Task> GetActiveTasksAsync()
+ {
+ List taskObj = (await _dbContext.TaskDetails
+ .Where(task => task.Status == Status.ACTIVE)
+ .ToListAsync().ConfigureAwait(false));
+ return taskObj;
+ }
+
+ public async Task GetTaskByIdAsync(int id)
+ {
+ TaskDetails? taskObj = await _dbContext.TaskDetails.FindAsync(id).ConfigureAwait(false);
+ return taskObj;
+ }
+
+ public async Task InsertTaskAsync(TaskDetails taskDetails)
+ {
+ _dbContext.TaskDetails.Add(taskDetails);
+ await _dbContext.SaveChangesAsync().ConfigureAwait(false);
+
+ return taskDetails.Id;
+ }
+
+ public async Task UpdateTaskAsync(TaskDetailsRequest modifiedDetails, TaskDetails existingDetails)
+ {
+ // Modify data
+ existingDetails.Description = modifiedDetails.Description;
+ existingDetails.Category = modifiedDetails.Category;
+ existingDetails.BudgetedHours = modifiedDetails.BudgetedHours;
+ existingDetails.AssignedTo = modifiedDetails.AssignedTo;
+ existingDetails.ModifiedOn = DateTime.UtcNow;
+
+ await _dbContext.SaveChangesAsync().ConfigureAwait(false);
+ return existingDetails;
+ }
+
+ public async Task InactiveTaskAsync(TaskDetails existingDetails)
+ {
+ // Modify task to INACTIVE
+ existingDetails.Status = Status.INACTIVE;
+ existingDetails.ModifiedOn = DateTime.UtcNow;
+
+ await _dbContext.SaveChangesAsync().ConfigureAwait(false);
+ return existingDetails;
+ }
+}
\ No newline at end of file
diff --git a/DotnetFoundation/DotnetFoundation.Infrastructure/SqlDatabaseContext.cs b/DotnetFoundation/DotnetFoundation.Infrastructure/SqlDatabaseContext.cs
index 20045bd..a5d5cf8 100644
--- a/DotnetFoundation/DotnetFoundation.Infrastructure/SqlDatabaseContext.cs
+++ b/DotnetFoundation/DotnetFoundation.Infrastructure/SqlDatabaseContext.cs
@@ -1,6 +1,6 @@
namespace DotnetFoundation.Infrastructure;
-
+using DotnetFoundation.Domain.Entities;
using DotnetFoundation.Infrastructure.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
@@ -12,6 +12,7 @@ public SqlDatabaseContext(DbContextOptions options) : base(o
}
public DbSet ApplicationUsers { get; set; }
+ public DbSet TaskDetails { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
@@ -24,8 +25,18 @@ protected override void OnModelCreating(ModelBuilder builder)
.HasOne(au => au.IdentityApplicationUser)
.WithOne(iu => iu.ApplicationUser)
.HasForeignKey(au => au.IdentityApplicationUserId);
- }
+ // for tasks
+ builder.Entity()
+ .HasKey(t => t.Id);
+
+ builder.Entity()
+ .HasIndex(t => t.Status);
+ builder.Entity()
+ .HasIndex(t => t.AssignedTo);
+
+ builder.Entity().ToTable("tasks");
+ }
}
diff --git a/DotnetFoundation/DotnetFoundation.Services/DependencyInjection.cs b/DotnetFoundation/DotnetFoundation.Services/DependencyInjection.cs
index 63bd29a..477eec7 100644
--- a/DotnetFoundation/DotnetFoundation.Services/DependencyInjection.cs
+++ b/DotnetFoundation/DotnetFoundation.Services/DependencyInjection.cs
@@ -1,5 +1,6 @@
using DotnetFoundation.Application.Interfaces.Services;
using DotnetFoundation.Services.Services.Authentication;
+using DotnetFoundation.Services.Services.TaskDetailsService;
using DotnetFoundation.Services.Services.UserService;
using Microsoft.Extensions.DependencyInjection;
@@ -11,6 +12,7 @@ public static IServiceCollection AddServices(this IServiceCollection services)
// Configure service scope for services / BLLs
services.AddScoped();
services.AddScoped();
+ services.AddScoped();
return services;
}
diff --git a/DotnetFoundation/DotnetFoundation.Services/Services/TaskDetailsService/TaskDetailsService.cs b/DotnetFoundation/DotnetFoundation.Services/Services/TaskDetailsService/TaskDetailsService.cs
new file mode 100644
index 0000000..675de83
--- /dev/null
+++ b/DotnetFoundation/DotnetFoundation.Services/Services/TaskDetailsService/TaskDetailsService.cs
@@ -0,0 +1,95 @@
+using AutoMapper;
+using DotnetFoundation.Application.Interfaces.Persistence;
+using DotnetFoundation.Application.Interfaces.Services;
+using DotnetFoundation.Application.Models.DTOs.TaskDetailsDTO;
+using DotnetFoundation.Domain.Entities;
+using DotnetFoundation.Domain.Enums;
+
+namespace DotnetFoundation.Services.Services.TaskDetailsService;
+
+public class TaskDetailsService : ITaskDetailsService
+{
+ private readonly ITaskDetailsRepository _taskDetailsRepository;
+ private readonly IUserRepository _userRepository;
+ private readonly IMapper _mapper;
+
+ public TaskDetailsService(ITaskDetailsRepository taskDetailsRepository, IMapper mapper, IUserRepository userRepository)
+ {
+ _taskDetailsRepository = taskDetailsRepository;
+ _userRepository = userRepository;
+ _mapper = mapper;
+ }
+
+
+ public async Task> GetAllTasksAsync()
+ {
+ List response = await _taskDetailsRepository.GetAllTasksAsync().ConfigureAwait(false);
+ return _mapper.Map>(response);
+ }
+
+ public async Task> GetActiveTasksAsync()
+ {
+ List response = await _taskDetailsRepository.GetActiveTasksAsync().ConfigureAwait(false);
+ return _mapper.Map>(response);
+ }
+
+ public async Task GetTaskByIdAsync(int id)
+ {
+ TaskDetails response = await _taskDetailsRepository.GetTaskByIdAsync(id).ConfigureAwait(false)
+ ?? throw new Exception($"Task with Id={id} does not exist");
+ return _mapper.Map(response);
+ }
+
+ public async Task InsertTaskAsync(TaskDetailsRequest detailsRequest)
+ {
+ User? user = await _userRepository.GetUserByIdAsync(detailsRequest.AssignedTo).ConfigureAwait(false)
+ ?? throw new Exception($"AssignedTo with userId = \"{detailsRequest.AssignedTo}\" does not exist. Cannot add task.");
+
+ // Create new TaskDetails object and add relevant details
+ TaskDetails taskDetails = new TaskDetails
+ {
+ Description = detailsRequest.Description,
+ BudgetedHours = detailsRequest.BudgetedHours,
+ AssignedTo = detailsRequest.AssignedTo,
+ Category = detailsRequest.Category,
+ Status = Status.ACTIVE,
+ CreatedBy = detailsRequest.AssignedTo,
+ ModifiedBy = detailsRequest.AssignedTo,
+ ModifiedOn = DateTime.UtcNow,
+ };
+
+ int? taskId = await _taskDetailsRepository.InsertTaskAsync(taskDetails).ConfigureAwait(false)
+ ?? throw new Exception($"Error inserting TaskDetails for \"{detailsRequest.Description}\"");
+
+ taskDetails.Id = (int)taskId;
+
+ return _mapper.Map(taskDetails);
+ }
+
+ public async Task UpdateTaskAsync(int id, TaskDetailsRequest modifiedDetails)
+ {
+ TaskDetails? existingDetails = await _taskDetailsRepository.GetTaskByIdAsync(id).ConfigureAwait(false)
+ ?? throw new Exception($"Task with Id={id} does not exist");
+
+ User? user = await _userRepository.GetUserByIdAsync(modifiedDetails.AssignedTo).ConfigureAwait(false)
+ ?? throw new Exception($"AssignedTo with userId = \"{modifiedDetails.AssignedTo}\" does not exist. Cannot add task.");
+
+ TaskDetails? modifiedTask = await _taskDetailsRepository.UpdateTaskAsync(modifiedDetails, existingDetails).ConfigureAwait(false)
+ ?? throw new Exception($"An error occurred while updating Task with id = \"{id}\"");
+
+ return _mapper.Map(modifiedTask);
+ }
+
+ public async Task InactiveTaskAsync(int id)
+ {
+ TaskDetails? existingDetails = await _taskDetailsRepository.GetTaskByIdAsync(id).ConfigureAwait(false);
+ if (existingDetails == null)
+ {
+ throw new Exception($"Task with Id = \"{id}\" does not exist");
+ }
+
+ TaskDetails? response = await _taskDetailsRepository.InactiveTaskAsync(existingDetails).ConfigureAwait(false)
+ ?? throw new Exception($"Error while deactivating Task id = \"{id}\"");
+ return _mapper.Map(response);
+ }
+}
\ No newline at end of file