mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 10:43:13 +00:00
Add null safety checks across all API controllers
- Add null checks after FirstOrDefault() before property access - Guard navigation property access (Locations, AssignToUser, ApplicationUser, POC, Contacts) - Null-coalesce string properties in search/filter LINQ queries - Protect Sum() on nullable LineItems collections - Change FirstAsync to FirstOrDefaultAsync with null guard in UserController - Add null check on model.Attachments iteration in EditWorkorder
This commit is contained in:
parent
128ae44a0d
commit
e8c400a20a
6 changed files with 59 additions and 47 deletions
|
|
@ -30,7 +30,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
try
|
||||
{
|
||||
var allUsersQuery = _db.Users
|
||||
.Where(w => w.FirstName.ToLower().Contains(search.ToLower()))
|
||||
.Where(w => (w.FirstName ?? "").ToLower().Contains((search ?? "").ToLower()))
|
||||
.OrderByDescending(d => d.Id);
|
||||
|
||||
var totalCount = allUsersQuery.Count();
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
try
|
||||
{
|
||||
var exist = _db.Contacts.Where(w => w.Id == contacts.Id).FirstOrDefault();
|
||||
if (exist == null)
|
||||
return BadRequest(new Response { Status = "Error", Message = "Contact not found" });
|
||||
|
||||
exist.Title = contacts.Title;
|
||||
exist.Owner = contacts.Owner;
|
||||
|
|
@ -260,7 +262,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
public IActionResult GetAddressbook(string? search = "", int page = 1, int pageSize = 10)
|
||||
{
|
||||
var totalCount = _db.Locations.Count();
|
||||
var data = _db.Locations.Where(w=> w.Name.ToLower().Contains(search.ToLower()) || w.Title.ToLower().Contains(search.ToLower())).Select(n => new
|
||||
var data = _db.Locations.Where(w=> (w.Name ?? "").ToLower().Contains(search.ToLower()) || (w.Title ?? "").ToLower().Contains(search.ToLower())).Select(n => new
|
||||
{
|
||||
n.Id,
|
||||
n.Name,
|
||||
|
|
|
|||
|
|
@ -158,13 +158,13 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
public IActionResult GetQuotes(string search = "", int page = 1, int pageSize = 10)
|
||||
{
|
||||
var totalCount = _db.Quotes.Count();
|
||||
var data = _db.Quotes.Include(s => s.WorkOrder).AsNoTracking().Where(w => w.QuotId.ToLower().Contains(search.ToLower()) || w.SiteName.ToLower().Contains(search.ToLower()) || w.WorkOrder.WorkerOrderTitle.ToLower().Contains(search.ToLower())).Select(s => new
|
||||
var data = _db.Quotes.Include(s => s.WorkOrder).AsNoTracking().Where(w => (w.QuotId ?? "").ToLower().Contains(search.ToLower()) || (w.SiteName ?? "").ToLower().Contains(search.ToLower()) || (w.WorkOrder != null && (w.WorkOrder.WorkerOrderTitle ?? "").ToLower().Contains(search.ToLower()))).Select(s => new
|
||||
{
|
||||
s.Id,
|
||||
QuoteId = "QO-" + s.QuotId,
|
||||
WorkOrder = s.WorkOrder != null ? s.WorkOrder.WorkerOrderNumber : "",
|
||||
s.ProjectName,
|
||||
TotalAmount = "$" + s.LineItems.Sum(s => s.Lineitem.Value).ToString(),
|
||||
TotalAmount = "$" + (s.LineItems != null ? s.LineItems.Sum(l => l.Lineitem ?? 0) : 0).ToString(),
|
||||
s.SiteName,
|
||||
s.SiteId,
|
||||
s.PO,
|
||||
|
|
@ -201,8 +201,8 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
s.Id,
|
||||
s.PO,
|
||||
s.TT,
|
||||
s.Locations.Title,
|
||||
s.Locations.Name
|
||||
Title = s.Locations != null ? s.Locations.Title : "",
|
||||
Name = s.Locations != null ? s.Locations.Name : ""
|
||||
}).ToListAsync();
|
||||
return Ok(data);
|
||||
}
|
||||
|
|
@ -216,7 +216,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
s.Id,
|
||||
s.QuotId,
|
||||
s.Date,
|
||||
Name = (s.Contacts.FirstName + " " + s.Contacts.LastName).Trim(),
|
||||
Name = s.Contacts != null ? (s.Contacts.FirstName + " " + s.Contacts.LastName).Trim() : "",
|
||||
s.PO,
|
||||
s.TT,
|
||||
s.SiteName,
|
||||
|
|
@ -225,7 +225,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
s.BillingAddress,
|
||||
s.ShippingAddress,
|
||||
lineitems = s.LineItems.Select(q => new { q.Descriptions, q.Lineitem }),
|
||||
TotalAmount = "$" + s.LineItems.Sum(s => s.Lineitem.Value).ToString()
|
||||
TotalAmount = "$" + (s.LineItems != null ? s.LineItems.Sum(l => l.Lineitem ?? 0) : 0).ToString()
|
||||
}).FirstOrDefaultAsync();
|
||||
return Ok(data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
try
|
||||
{
|
||||
var exist = _db.Categories.Where(w => w.Id == model.Id).FirstOrDefault();
|
||||
if (exist == null)
|
||||
return BadRequest(new Response { Status = "Error", Message = "Category not found" });
|
||||
exist.Name = model.Name;
|
||||
_db.Categories.Update(exist);
|
||||
await _db.SaveChangesAsync();
|
||||
|
|
@ -157,7 +159,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
try
|
||||
{
|
||||
var totalCount = _db.Users.Count();
|
||||
var allUsers = _db.Users.Where(w => w.FirstName.ToLower().Contains(search.ToLower())).OrderByDescending(d => d.Id).ToList().Skip((page - 1) * pageSize)
|
||||
var allUsers = _db.Users.Where(w => (w.FirstName ?? "").ToLower().Contains((search ?? "").ToLower())).OrderByDescending(d => d.Id).ToList().Skip((page - 1) * pageSize)
|
||||
.Take(pageSize);
|
||||
|
||||
// Calculate the number of pages
|
||||
|
|
|
|||
|
|
@ -94,7 +94,9 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
else
|
||||
{
|
||||
|
||||
var exist1 = await _userManager.Users.FirstAsync(w => w.Id == model.Id);
|
||||
var exist1 = await _userManager.Users.FirstOrDefaultAsync(w => w.Id == model.Id);
|
||||
if (exist1 == null)
|
||||
return BadRequest(new Response { Status = "Error", Message = "User not found" });
|
||||
|
||||
var existingRole = await _userManager.GetRolesAsync(exist1);
|
||||
|
||||
|
|
@ -134,6 +136,8 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
try
|
||||
{
|
||||
var exist = _db.Users.Where(w => w.Id == user.Id).FirstOrDefault();
|
||||
if (exist == null)
|
||||
return BadRequest(new Response { Status = "Error", Message = "User not found" });
|
||||
exist.FirstName = user.Name;
|
||||
exist.EmailConfirmed = true;
|
||||
exist.UserName = user.Email;
|
||||
|
|
|
|||
|
|
@ -180,6 +180,8 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
try
|
||||
{
|
||||
var workOrder = _db.workOrders.Where(w => w.Id == model.Id).FirstOrDefault();
|
||||
if (workOrder == null)
|
||||
return BadRequest(new Response { Status = "Error", Message = "Work order not found" });
|
||||
workOrder.WorkerOrderNumber = model.WorkerOrderNumber;
|
||||
workOrder.WorkerOrderTitle = model.WorkerOrderTitle;
|
||||
workOrder.Description = model.Description;
|
||||
|
|
@ -227,27 +229,28 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
|
||||
#region Images of workorder
|
||||
workOrder.workOrderAttachments = workOrder.workOrderAttachments == null ? new List<WorkOrderAttachments>() : 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));
|
||||
|
||||
using (var ms = System.IO.File.Create(fullPath))
|
||||
{
|
||||
await attachment.CopyToAsync(ms);
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
@ -455,10 +458,11 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
|
||||
if (!string.IsNullOrEmpty(search))
|
||||
{
|
||||
var s = search.ToLower();
|
||||
query = query.Where(w =>
|
||||
w.WorkerOrderTitle.ToLower().Contains(search.ToLower()) ||
|
||||
w.WorkerOrderNumber.ToLower().Contains(search.ToLower()) ||
|
||||
w.Locations.Title.ToLower().Contains(search.ToLower()));
|
||||
(w.WorkerOrderTitle ?? "").ToLower().Contains(s) ||
|
||||
(w.WorkerOrderNumber ?? "").ToLower().Contains(s) ||
|
||||
(w.Locations != null && (w.Locations.Title ?? "").ToLower().Contains(s)));
|
||||
}
|
||||
|
||||
if (assignto != null && assignto.Length > 0)
|
||||
|
|
@ -515,7 +519,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
var pagedData = data
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.Select(s => new { s.Id, s.WorkerOrderTitle, s.DueDate, s.Status, s.Priority, s.Locations.Name })
|
||||
.Select(s => new { s.Id, s.WorkerOrderTitle, s.DueDate, s.Status, s.Priority, Name = s.Locations != null ? s.Locations.Name : "" })
|
||||
.OrderByDescending(d => d.Name)
|
||||
.ToList();
|
||||
|
||||
|
|
@ -551,16 +555,14 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
title = s.WorkerOrderTitle,
|
||||
s.DueDate,
|
||||
s.Status,
|
||||
assignee = s.AssignToUser.FirstName,
|
||||
location = s.Locations.Name,
|
||||
assignee = s.AssignToUser != null ? s.AssignToUser.FirstName : "",
|
||||
location = s.Locations != null ? s.Locations.Name : "",
|
||||
priority = s.Priority,
|
||||
s.PO,
|
||||
s.TT,
|
||||
poc = s.WorkOrderContacts.Select(s => new { s.Id, name = (s.POC.FirstName + " " + s.POC.LastName).Trim(), email = s.POC.Email, phone = s.POC.PhoneNumber }),
|
||||
category = s.WorkOrderCategories.Select(s => new { s.Id, name = s.Category.Name }),
|
||||
Attachments = s.workOrderAttachments.Select(s => new { s.Id, attachment = s.Attachments }),
|
||||
//category = s.Category.Name,
|
||||
//s.Attachments,
|
||||
poc = s.WorkOrderContacts.Select(c => new { c.Id, name = c.POC != null ? (c.POC.FirstName + " " + c.POC.LastName).Trim() : "", email = c.POC != null ? c.POC.Email : "", phone = c.POC != null ? c.POC.PhoneNumber : "" }),
|
||||
category = s.WorkOrderCategories.Select(c => new { c.Id, name = c.Category != null ? c.Category.Name : "" }),
|
||||
Attachments = s.workOrderAttachments.Select(a => new { a.Id, attachment = a.Attachments }),
|
||||
s.BeforPhotoIssue,
|
||||
s.BeforPhotoAttachment,
|
||||
s.AfterPhotoIssue,
|
||||
|
|
@ -568,7 +570,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
s.SignOffName,
|
||||
s.SignOffAttachment,
|
||||
s.SignOffSignature,
|
||||
Comments = s.Comments.Select(s => new { s.Id, s.CreatedDate, s.Commenttext, s.Documents, userName = s.ApplicationUser.FirstName }),
|
||||
Comments = s.Comments.Select(c => new { c.Id, c.CreatedDate, c.Commenttext, c.Documents, userName = c.ApplicationUser != null ? c.ApplicationUser.FirstName : "" }),
|
||||
quotes = s.Quotes.Select(q => new { code = q.QuotId, q.Id })
|
||||
}).FirstOrDefaultAsync();
|
||||
if (exist == null)
|
||||
|
|
@ -615,7 +617,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
|
||||
var currentDate = DateTime.UtcNow.Date;
|
||||
var data = _db.workOrders.Include(w => w.Locations)
|
||||
.Where(w => w.istemplate != true && ((w.WorkerOrderTitle.ToLower().Contains(search.ToLower()) || w.WorkerOrderNumber.ToLower().Contains(search.ToLower()) || w.Locations.Title.ToLower().Contains(search.ToLower())) &&
|
||||
.Where(w => w.istemplate != true && (((w.WorkerOrderTitle ?? "").ToLower().Contains(search.ToLower()) || (w.WorkerOrderNumber ?? "").ToLower().Contains(search.ToLower()) || (w.Locations != null && (w.Locations.Title ?? "").ToLower().Contains(search.ToLower()))) &&
|
||||
(assignto.Count() == 0 || assignto.Contains(w.AssignTo)) &&
|
||||
(location.Count() == 0 || (w.LocationId.HasValue && location.Contains(w.LocationId.Value))) &&
|
||||
(priority.Count() == 0 || priority.Contains(w.Priority)) &&
|
||||
|
|
@ -647,7 +649,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
break;
|
||||
}
|
||||
}
|
||||
var newdata = data.Select(s => new { s.Id, s.WorkerOrderTitle, s.DueDate, s.Status, s.Priority, s.Locations.Name }).OrderByDescending(d => d.Name).ToList().Skip((page - 1) * pageSize)
|
||||
var newdata = data.Select(s => new { s.Id, s.WorkerOrderTitle, s.DueDate, s.Status, s.Priority, Name = s.Locations != null ? s.Locations.Name : "" }).OrderByDescending(d => d.Name).ToList().Skip((page - 1) * pageSize)
|
||||
.Take(pageSize);
|
||||
var totalPages1 = (int)Math.Ceiling(totalCount / (double)pageSize);
|
||||
|
||||
|
|
@ -672,7 +674,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
s.DueDate,
|
||||
s.Status,
|
||||
s.Priority,
|
||||
s.Locations.Name
|
||||
Name = s.Locations != null ? s.Locations.Name : ""
|
||||
}).OrderByDescending(d => d.Id).ToList().Skip((page - 1) * pageSize)
|
||||
.Take(pageSize);
|
||||
|
||||
|
|
@ -711,6 +713,8 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
try
|
||||
{
|
||||
var data = await _db.workOrders.Where(w => w.Id == id).FirstOrDefaultAsync();
|
||||
if (data == null)
|
||||
return BadRequest(new Response { Status = "Error", Message = "Work order not found" });
|
||||
data.Status = status;
|
||||
await _db.SaveChangesAsync();
|
||||
return Ok(new DataResponse { Message = "Updated Successfully", Status = "200", Data = data });
|
||||
|
|
@ -770,7 +774,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
{
|
||||
s.Id,
|
||||
s.Commenttext,
|
||||
s.ApplicationUser.FirstName,
|
||||
FirstName = s.ApplicationUser != null ? s.ApplicationUser.FirstName : "",
|
||||
s.Documents
|
||||
}).ToListAsync();
|
||||
return Ok(data);
|
||||
|
|
@ -784,7 +788,7 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
{
|
||||
s.Id,
|
||||
s.Commenttext,
|
||||
s.ApplicationUser.FirstName,
|
||||
FirstName = s.ApplicationUser != null ? s.ApplicationUser.FirstName : "",
|
||||
s.Documents
|
||||
}).ToListAsync();
|
||||
return Ok(data);
|
||||
|
|
@ -815,8 +819,8 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
WorkerOrderNumber = s.WorkerOrderNumber,
|
||||
WorkerOrderTitle = s.WorkerOrderTitle,
|
||||
DueDate = s.DueDate,
|
||||
AssignToUserName = s.AssignToUser.FirstName,
|
||||
LocationName = s.Locations.Name,
|
||||
AssignToUserName = s.AssignToUser != null ? s.AssignToUser.FirstName : "",
|
||||
LocationName = s.Locations != null ? s.Locations.Name : "",
|
||||
LocationId = s.LocationId,
|
||||
PO = s.PO,
|
||||
TT = s.TT,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue