diff --git a/Api.SeaHavenIndustries/Api.SeaHavenIndustries.csproj b/Api.SeaHavenIndustries/Api.SeaHavenIndustries.csproj index 82190f7..663aadd 100644 --- a/Api.SeaHavenIndustries/Api.SeaHavenIndustries.csproj +++ b/Api.SeaHavenIndustries/Api.SeaHavenIndustries.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -10,6 +10,7 @@ + diff --git a/Api.SeaHavenIndustries/Controllers/AuthenticationController.cs b/Api.SeaHavenIndustries/Controllers/AuthenticationController.cs index bc9f44d..27d1a6c 100644 --- a/Api.SeaHavenIndustries/Controllers/AuthenticationController.cs +++ b/Api.SeaHavenIndustries/Controllers/AuthenticationController.cs @@ -15,7 +15,7 @@ using System.Diagnostics; namespace Api.SeaHavenIndustries.Controllers { [ApiController] - [Route("[controller]")] + [Route("api/Authentication")] public class AuthenticationController : Controller { private readonly UserManager _userManager; diff --git a/Api.SeaHavenIndustries/Controllers/ContactController.cs b/Api.SeaHavenIndustries/Controllers/ContactController.cs index 3310814..2a60a5f 100644 --- a/Api.SeaHavenIndustries/Controllers/ContactController.cs +++ b/Api.SeaHavenIndustries/Controllers/ContactController.cs @@ -4,12 +4,13 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using SendGrid.Helpers.Mail; namespace Api.SeaHavenIndustries.Controllers { [Authorize] [ApiController] - [Route("[controller]")] + [Route("api/Contact")] public class ContactController : Controller { private readonly UserManager _userManager; @@ -110,6 +111,45 @@ namespace Api.SeaHavenIndustries.Controllers return Ok(viewModel); } + [HttpGet] + [Route("GetContacts")] + public async Task GetContacts() + { + var data = await _db.Contacts.ToListAsync(); + return Ok(data); + } + [HttpGet] + [Route("GetLocations")] + public async Task GetLocations() + { + var data = await _db.Locations.Select(s => new LocationViewModel + { + Id = s.Id, + Name = s.Title + " - " + s.Name + }).ToListAsync(); + return Ok(data); + } + + [HttpGet] + [Route("GetCategories")] + public async Task GetCategories() + { + var data = await _db.Categories.ToListAsync(); + return Ok(data); + } + + [HttpGet] + [Route("GetUsers")] + public async Task GetUsers() + { + var filteredUsers = await (from user in _db.Users + where !(from userRole in _db.UserRoles + join role in _db.Roles on userRole.RoleId equals role.Id + where role.Name == "Admin" || role.Name == "Manager" + select userRole.UserId).Contains(user.Id) + select user).ToListAsync(); + return Ok(filteredUsers); + } [HttpPost] [Route("AddLocation")] public async Task AddLocation(Location_DTO model) @@ -207,5 +247,11 @@ namespace Api.SeaHavenIndustries.Controllers return Ok(viewModel); } + public class LocationViewModel + { + public int? Id { get; set; } + public string? Name { get; set; } + } + } } diff --git a/Api.SeaHavenIndustries/Controllers/QuotesController.cs b/Api.SeaHavenIndustries/Controllers/QuotesController.cs index 6fd953c..37f7f55 100644 --- a/Api.SeaHavenIndustries/Controllers/QuotesController.cs +++ b/Api.SeaHavenIndustries/Controllers/QuotesController.cs @@ -12,7 +12,7 @@ namespace Api.SeaHavenIndustries.Controllers { [Authorize] [ApiController] - [Route("[controller]")] + [Route("api/Quotes")] public class QuotesController : Controller { private readonly UserManager _userManager; @@ -32,8 +32,10 @@ namespace Api.SeaHavenIndustries.Controllers { try { + Random rnd = new Random(); + int id = rnd.Next(1, 99999); Quotes quotes = new Quotes(); - quotes.QuotId = model.QuotId; + quotes.QuotId = id.ToString(); quotes.ContactId = model.ContactId; quotes.PO = model.PO; quotes.TT = model.TT; @@ -67,7 +69,7 @@ namespace Api.SeaHavenIndustries.Controllers } } - [HttpPost] + [HttpPut] [Route("EditQuote")] public async Task EditQuote([FromBody] EditQuote_DTO model) { @@ -121,10 +123,11 @@ namespace Api.SeaHavenIndustries.Controllers } } - [HttpGet] + [HttpDelete] [Route("DeleteQuote")] - public IActionResult DeleteQuote(int id) + public IActionResult DeleteQuote(EditQuote_DTO model) { + int id = model.id; try { var data = _db.Quotes.Where(w => w.Id == id).FirstOrDefault(); @@ -159,11 +162,18 @@ namespace Api.SeaHavenIndustries.Controllers { s.Id, QuoteId = "QO-" + s.QuotId, - WOID = s.WorkOrder != null ? s.WorkOrder.WorkerOrderNumber : "", + WorkOrder = s.WorkOrder != null ? s.WorkOrder.WorkerOrderNumber : "", s.ProjectName, TotalAmount = "$" + s.LineItems.Sum(s => s.Lineitem.Value).ToString(), - siteName = s.SiteName, - status = s.Status + s.SiteName, + s.SiteId, + s.PO, + s.TT, + s.BillingAddress, + s.Status, + s.ContactId, + s.Date, + lineitems = s.LineItems.Select(q => new { q.Descriptions, q.Lineitem, q.LineitemNumber}), }).OrderByDescending(d => d.Id).ToList().Skip((page - 1) * pageSize) .Take(pageSize); diff --git a/Api.SeaHavenIndustries/Controllers/UserController.cs b/Api.SeaHavenIndustries/Controllers/UserController.cs index 7b91a01..f37f652 100644 --- a/Api.SeaHavenIndustries/Controllers/UserController.cs +++ b/Api.SeaHavenIndustries/Controllers/UserController.cs @@ -1,10 +1,13 @@ using Api.SeaHavenIndustries.DTOs; using Api.SeaHavenIndustries.Helper; +using Api.SeaHavenIndustries.Models; using Data.SeaHavenIndustries; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using PasswordGenerator; +using SendGrid.Helpers.Mail; using System.Security.Claims; using System.Security.Cryptography; @@ -12,7 +15,7 @@ namespace Api.SeaHavenIndustries.Controllers { [Authorize] [ApiController] - [Route("[controller]")] + [Route("api/User")] public class UserController : Controller { private readonly UserManager _userManager; @@ -25,46 +28,106 @@ namespace Api.SeaHavenIndustries.Controllers _db = db; _sendemail = sendemail; } + [Route("")] + [HttpGet] + public async Task GetUsers() + { + _db.ChangeTracker.Clear(); + + var allUsers = _db.Users.Select(s => new UserRoleViewModel + { + RoleName = s.PhoneNumber, + Email = s.Email, + Name = s.FirstName, + Date = s.CreatedDate != null ? s.CreatedDate.Value.Date.ToString("MMM dd yyyy") : "", + Status = s.UniqueName, + Id = s.Id + }).AsQueryable(); + return Ok(allUsers); + } [HttpPost] [Route("AddUser")] - public async Task AddUser(User_DTO model) + public async Task AddUser(User_DTO user) { + + var model = new ApplicationUser + { + UserName = user.Email, + FirstName = user.Name, + Email = user.Email, + }; + try { - ApplicationUser user = new ApplicationUser(); - user.EmailConfirmed = true; - user.UserName = model.Email; - user.Email = model.Email; - user.FirstName = model.Name; - user.CreatedDate = DateTime.Now; - user.UniqueName = "Active"; - var password = GenerateRandomPassword(8); - var result = await _userManager.CreateAsync(user, password); - if (result.Succeeded) + _db.ChangeTracker.Clear(); + var exist = _db.Set().Find(model.Id); + if (exist == null) { - await _userManager.AddToRoleAsync(user, model.Role ?? ""); + model.EmailConfirmed = true; + model.UserName = model.Email; + model.CreatedDate = DateTime.Now; + model.UniqueName = "Active"; + model.PhoneNumber = user.Role; + + var pwd = new Password(8).IncludeLowercase().IncludeUppercase().IncludeSpecial().IncludeNumeric(); + var password = pwd.Next(); + + var result = await _userManager.CreateAsync(model, password); + if (result.Succeeded) + { + await _userManager.AddToRoleAsync(model, user.Role ?? ""); + } + else + { + return BadRequest(new Response { Status = "Error", Message = result.Errors.FirstOrDefault()?.Description ?? "error" }); + } + var request = HttpContext?.Request; + //var domain = $"{request?.Scheme}://{request?.Host}"; + var domain = "http://shoc-ui-app.s3-website-us-east-1.amazonaws.com/#"; + string subject = "Login Information"; + string greeting = $"Dear {model.FirstName},\n\n"; + string loginLink = $"Click here to login:Login\n"; + string passwordInfo = $"Your password is: {password}\n\n"; + string body = $"{greeting}\n\n{loginLink}\n\n{passwordInfo}"; + await _sendemail.SendEMail(model?.Email ?? "", subject, body); } else { - return BadRequest(result.Errors.FirstOrDefault()?.Description ?? "error"); - } - //var request = _httpContextAccessor.HttpContext?.Request; - //var domain = $"{request?.Scheme}://{request?.Host}"; - string subject = "Login Information"; - //string greeting = $"Dear {model.FirstName},\n\n"; - //string loginLink = $"Click here to login:{domain}/Login\n"; - string passwordInfo = $"Your password is: {password}\n\n"; - string body = $"{passwordInfo}"; - await _sendemail.SendEMail(model?.Email ?? "", subject, body); + var exist1 = await _userManager.Users.FirstAsync(w => w.Id == model.Id); + + var existingRole = await _userManager.GetRolesAsync(exist1); + + // Remove from roles if any exist + if (existingRole != null && existingRole.Any() && existingRole.FirstOrDefault() != exist1.PhoneNumber) + { + await _userManager.RemoveFromRolesAsync(exist1, existingRole); + } + + // Update user details + exist1.FirstName = model.FirstName; + exist1.LastName = model.LastName; + exist1.Contact = model.Contact; + exist1.PhoneNumber = model.PhoneNumber; + + // Optionally, detach the entity if you're about to attach it again + _db.Entry(exist1).State = EntityState.Detached; + + // Add to role after setting properties + await _userManager.AddToRoleAsync(exist1, user.Role ?? ""); + var result = await _userManager.UpdateAsync(exist1); + //await _context.SaveChangesAsync(); + } return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" }); + } catch (Exception ex) { return BadRequest(new Response { Status = "Error", Message = ex.Message }); + } } - [HttpPost] + [HttpPut] [Route("EditUser")] public async Task EditUser(EditUser_DTO user) { @@ -79,6 +142,7 @@ namespace Api.SeaHavenIndustries.Controllers exist.NormalizedUserName = user.Email.ToUpper(); exist.CreatedDate = DateTime.Now; exist.UniqueName = "Active"; + exist.PhoneNumber = user.Role; var existingRole = await _userManager.GetRolesAsync(exist); if (existingRole != null && existingRole.Any()) @@ -95,11 +159,17 @@ namespace Api.SeaHavenIndustries.Controllers return BadRequest(new Response { Status = "Error", Message = ex.Message }); } } - - [HttpGet] - [Route("DeleteUser")] - public async Task DeleteUser(string id) + public class DeleteUserRequest { + public string Id { get; set; } + } + + + [HttpDelete] + [Route("DeleteUser")] + public async Task DeleteUser(EditUser_DTO req) + { + string id = req.Id; try { var data = await _db.Users.Where(w => w.Id == id).FirstOrDefaultAsync(); diff --git a/Api.SeaHavenIndustries/Controllers/WorkOrderController.cs b/Api.SeaHavenIndustries/Controllers/WorkOrderController.cs index eddf3c3..91b4cc2 100644 --- a/Api.SeaHavenIndustries/Controllers/WorkOrderController.cs +++ b/Api.SeaHavenIndustries/Controllers/WorkOrderController.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; +using SendGrid.Helpers.Mail; using System.IO; using System.Net.Http.Headers; using System.Security.Claims; @@ -16,7 +17,7 @@ namespace Api.SeaHavenIndustries.Controllers { [Authorize] [ApiController] - [Route("[controller]")] + [Route("api/WorkOrder")] public class WorkOrderController : Controller { private readonly UserManager _userManager; @@ -76,28 +77,31 @@ namespace Api.SeaHavenIndustries.Controllers #region Images of workorder workOrder.workOrderAttachments = workOrder.workOrderAttachments == null ? new List() : workOrder.workOrderAttachments; - foreach (var attachment in model.Attachments) + if (model.Attachments != null) { - string fileName = ContentDispositionHeaderValue.Parse(attachment.ContentDisposition).FileName.Trim('"'); - string uniqueFileName = $"{Guid.NewGuid()}_{fileName}"; - - string uploadProfilePath = Path.Combine("Assets", "Documents"); - string fullPath = Path.Combine(_webHostEnvironment.WebRootPath, uploadProfilePath, uniqueFileName); - - Directory.CreateDirectory(Path.GetDirectoryName(fullPath)); - - // Copy the file to the server - using (var ms = System.IO.File.Create(fullPath)) + foreach (var attachment in model.Attachments) { - await attachment.CopyToAsync(ms); - } + string fileName = ContentDispositionHeaderValue.Parse(attachment.ContentDisposition).FileName.Trim('"'); + string uniqueFileName = $"{Guid.NewGuid()}_{fileName}"; - // Update the user's image URL - var request = _httpContext.HttpContext.Request; - var domain = $"{request.Scheme}://{request.Host}"; - var imagesPath = domain + "/" + Path.Combine(uploadProfilePath, uniqueFileName); - workOrder.workOrderAttachments.Add(new WorkOrderAttachments { Attachments = imagesPath }); - } + string uploadProfilePath = Path.Combine("Assets", "Documents"); + string fullPath = Path.Combine(_webHostEnvironment.WebRootPath, uploadProfilePath, uniqueFileName); + + Directory.CreateDirectory(Path.GetDirectoryName(fullPath)); + + // Copy the file to the server + using (var ms = System.IO.File.Create(fullPath)) + { + await attachment.CopyToAsync(ms); + } + + // Update the user's image URL + var request = _httpContext.HttpContext.Request; + var domain = $"{request.Scheme}://{request.Host}"; + var imagesPath = domain + "/" + Path.Combine(uploadProfilePath, uniqueFileName); + workOrder.workOrderAttachments.Add(new WorkOrderAttachments { Attachments = imagesPath }); + } + } if (model.BeforPhotoAttachment != null) { @@ -751,5 +755,57 @@ namespace Api.SeaHavenIndustries.Controllers }).ToListAsync(); return Ok(data); } + [HttpGet] + [Route("GetworkordersDD")] + public async Task GetworkordersDD() + { + _db.ChangeTracker.Clear(); + + var data = await _db.workOrders.Where(w => w.istemplate != true).Include(w => w.Locations).Include(w => w.AssignToUser).ToListAsync(); + return Ok(data); + } + [HttpGet] + [Route("Getworkorders")] + public async Task Getworkorders() + { + _db.ChangeTracker.Clear(); + var data = await _db.workOrders + .Where(w => w.istemplate != true) + .AsSplitQuery() + .Include(w => w.Locations) + .Include(w => w.AssignToUser).Select(s => new WorkorderFilterVM + { + Id = s.Id, + Priority = s.Priority, + Status = s.Status, + WorkerOrderNumber = s.WorkerOrderNumber, + WorkerOrderTitle = s.WorkerOrderTitle, + DueDate = s.DueDate, + AssignToUserName = s.AssignToUser.FirstName, + LocationName = s.Locations.Name, + LocationId = s.LocationId, + PO = s.PO, + TT = s.TT, + }).ToListAsync(); + return Ok(data); + } + public class WorkorderFilterVM + { + public int? Id { get; set; } + public int? LocationId { get; set; } + public string? WorkerOrderNumber { get; set; } + public string? BillingAddress { get; set; } = "Amazon.com Services LLC 410 Terry Ave,North Seattle, Washington, 98109"; + + public string? WorkerOrderTitle { get; set; } + public string? LocationName { get; set; } + public string? AssignToUserName { get; set; } + public string? Priority { get; set; } + public string? Status { get; set; } + public DateTime? DueDate { get; set; } + public string? Dispatcher { get; set; } + public string? Scheduler { get; set; } + public string? PO { get; set; } + public string? TT { get; set; } + } } } diff --git a/Api.SeaHavenIndustries/Models/UserRoleViewModel.cs b/Api.SeaHavenIndustries/Models/UserRoleViewModel.cs new file mode 100644 index 0000000..9fcc64a --- /dev/null +++ b/Api.SeaHavenIndustries/Models/UserRoleViewModel.cs @@ -0,0 +1,14 @@ +namespace Api.SeaHavenIndustries.Models +{ + public class UserRoleViewModel + { + public string? Id { get; set; } + public string? UserName { get; set; } + public string? Email { get; set; } + public string? RoleName { get; set; } + public string? Name { get; set; } + + public string? Status { get; set; } + public string? Date { get; set; } + } +} diff --git a/Api.SeaHavenIndustries/appsettings.json b/Api.SeaHavenIndustries/appsettings.json index 063218d..afdabec 100644 --- a/Api.SeaHavenIndustries/appsettings.json +++ b/Api.SeaHavenIndustries/appsettings.json @@ -3,10 +3,10 @@ //"DefaultConnection": "Server=DESKTOP-64LC14O\SQLEXPRESS;Database=SeahavenIndustries;TrustServerCertificate=True;Trusted_Connection=True;MultipleActiveResultSets=true", // Test database - "DefaultConnection": "Server=SQL5112.site4now.net;Initial Catalog=db_a7141e_seahavenindustries;User Id=db_a7141e_seahavenindustries_admin;Password=Abc123!@#;MultipleActiveResultSets=true" + //"DefaultConnection": "Server=SQL5112.site4now.net;Initial Catalog=db_a7141e_seahavenindustries;User Id=db_a7141e_seahavenindustries_admin;Password=Abc123!@#;MultipleActiveResultSets=true" //Client Database - //"DefaultConnection": "Server=SQL5112.site4now.net;Initial Catalog=db_a7141e_seahavenindustry;User Id=db_a7141e_seahavenindustry_admin;Password=Abc123!@#;MultipleActiveResultSets=true", + "DefaultConnection": "Server=SQL5112.site4now.net;Initial Catalog=db_a7141e_seahavenindustry;User Id=db_a7141e_seahavenindustry_admin;Password=Abc123!@#;MultipleActiveResultSets=true" }, "Logging": { "LogLevel": { @@ -14,6 +14,9 @@ "Microsoft.AspNetCore": "Warning" } }, + "SendGrid": { + "ApiKey": "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" + }, "AllowedHosts": "*", "JWT": { "ValidAudience": "http://localhost:4200", diff --git a/Api.SeaHavenIndustries/aws-beanstalk-tools-defaults.json b/Api.SeaHavenIndustries/aws-beanstalk-tools-defaults.json new file mode 100644 index 0000000..fab4ccf --- /dev/null +++ b/Api.SeaHavenIndustries/aws-beanstalk-tools-defaults.json @@ -0,0 +1,13 @@ + +{ + "region" : "us-east-1", + "configuration" : "Debug", + "framework" : "net8.0", + "self-contained" : true, + "application" : "SeaHavenIndustries", + "environment" : "SeaHavenIndustries-dev", + "enable-xray" : false, + "enhanced-health-type" : "basic", + "additional-options" : "", + "proxy-server" : "nginx" +} \ No newline at end of file diff --git a/SeaHavenIndustries/appsettings.json b/SeaHavenIndustries/appsettings.json index 4051e64..9e739e2 100644 --- a/SeaHavenIndustries/appsettings.json +++ b/SeaHavenIndustries/appsettings.json @@ -3,10 +3,10 @@ //"DefaultConnection": "Server=.;Database=SeahavenIndustries;TrustServerCertificate=True;Trusted_Connection=True;MultipleActiveResultSets=true", //"DefaultConnection": "Server=.\\SqlExpress;Database=SeahavenIndustries;TrustServerCertificate=True;Trusted_Connection=True;MultipleActiveResultSets=true", // Test database - "DefaultConnection": "Server=SQL5112.site4now.net;Initial Catalog=db_a7141e_seahavenindustries;User Id=db_a7141e_seahavenindustries_admin;Password=Abc123!@#;MultipleActiveResultSets=true", + //"DefaultConnection": "Server=SQL5112.site4now.net;Initial Catalog=db_a7141e_seahavenindustries;User Id=db_a7141e_seahavenindustries_admin;Password=Abc123!@#;MultipleActiveResultSets=true", //Client Database - //"DefaultConnection": "Server=SQL5112.site4now.net;Initial Catalog=db_a7141e_seahavenindustry;User Id=db_a7141e_seahavenindustry_admin;Password=Abc123!@#;MultipleActiveResultSets=true", + "DefaultConnection": "Server=SQL5112.site4now.net;Initial Catalog=db_a7141e_seahavenindustry;User Id=db_a7141e_seahavenindustry_admin;Password=Abc123!@#;MultipleActiveResultSets=true", "excelconnection": "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 8.0;HDR=YES'" }, "Logging": {