mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-10-03 17:53:22 +00:00
backend architectural template
This commit is contained in:
parent
ac76b201de
commit
5e4d9894e9
41 changed files with 2152 additions and 847 deletions
|
|
@ -2,17 +2,19 @@
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/Account")]
|
[Route("api/Account")]
|
||||||
[Route("api/accounts")]
|
[Route("api/accounts")]
|
||||||
public class AccountController : ControllerBase
|
public class AccountController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ApplicationDbContext _db;
|
private readonly IAccountService _accountService;
|
||||||
|
|
||||||
public AccountController(ApplicationDbContext db)
|
public AccountController(IAccountService accountService)
|
||||||
{
|
{
|
||||||
_db = db;
|
_accountService = accountService;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
|
|
@ -23,34 +25,16 @@ public class AccountController : ControllerBase
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var model = new Accounts
|
var createDto = new CreateAccountDTO
|
||||||
{
|
{
|
||||||
Name = dto.Name,
|
Name = dto.Name ?? throw new ArgumentException("Name is required"),
|
||||||
Type = dto.Type,
|
|
||||||
Importance = dto.Importance,
|
|
||||||
TerritoryId = dto.TerritoryId,
|
|
||||||
OwnerEmployeeId = dto.OwnerEmployeeId,
|
|
||||||
PrivacySetting = dto.PrivacySetting,
|
|
||||||
About = dto.About,
|
|
||||||
Tags = dto.Tags,
|
|
||||||
|
|
||||||
Phone = dto.Phone,
|
Phone = dto.Phone,
|
||||||
Email = dto.Email,
|
Email = dto.Email,
|
||||||
IndustryId = dto.IndustryId,
|
Website = dto.Website
|
||||||
TimeZone = dto.TimeZone,
|
|
||||||
Website = dto.Website,
|
|
||||||
CurrencyCode = dto.CurrencyCode,
|
|
||||||
ServiceInstructions = dto.ServiceInstructions,
|
|
||||||
|
|
||||||
FacebookUrl = dto.FacebookUrl,
|
|
||||||
LinkedInUrl = dto.LinkedInUrl,
|
|
||||||
TwitterUrl = dto.TwitterUrl,
|
|
||||||
|
|
||||||
CreatedDate = DateTime.UtcNow
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_db.Accounts.Add(model);
|
var userId = User.Identity?.Name ?? "system";
|
||||||
await _db.SaveChangesAsync();
|
await _accountService.CreateAccountAsync(createDto, userId);
|
||||||
|
|
||||||
return Ok(new DataResponse
|
return Ok(new DataResponse
|
||||||
{
|
{
|
||||||
|
|
@ -76,34 +60,16 @@ public class AccountController : ControllerBase
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var account = await _db.Accounts.FirstOrDefaultAsync(a => a.Id == dto.Id);
|
var updateDto = new UpdateAccountDTO
|
||||||
if (account == null)
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = "Account not found." });
|
Name = dto.Name,
|
||||||
|
Phone = dto.Phone,
|
||||||
|
Email = dto.Email,
|
||||||
|
Website = dto.Website
|
||||||
|
};
|
||||||
|
|
||||||
account.Name = dto.Name;
|
var userId = User.Identity?.Name ?? "system";
|
||||||
account.Type = dto.Type;
|
await _accountService.UpdateAccountAsync(dto.Id, updateDto, userId);
|
||||||
account.Importance = dto.Importance;
|
|
||||||
account.TerritoryId = dto.TerritoryId;
|
|
||||||
account.OwnerEmployeeId = dto.OwnerEmployeeId;
|
|
||||||
account.PrivacySetting = dto.PrivacySetting;
|
|
||||||
account.About = dto.About;
|
|
||||||
account.Tags = dto.Tags;
|
|
||||||
|
|
||||||
account.Phone = dto.Phone;
|
|
||||||
account.Email = dto.Email;
|
|
||||||
account.IndustryId = dto.IndustryId;
|
|
||||||
account.TimeZone = dto.TimeZone;
|
|
||||||
account.Website = dto.Website;
|
|
||||||
account.CurrencyCode = dto.CurrencyCode;
|
|
||||||
account.ServiceInstructions = dto.ServiceInstructions;
|
|
||||||
|
|
||||||
account.FacebookUrl = dto.FacebookUrl;
|
|
||||||
account.LinkedInUrl = dto.LinkedInUrl;
|
|
||||||
account.TwitterUrl = dto.TwitterUrl;
|
|
||||||
|
|
||||||
account.LastModificationTime = DateTime.UtcNow;
|
|
||||||
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Ok(new DataResponse
|
return Ok(new DataResponse
|
||||||
{
|
{
|
||||||
|
|
@ -129,12 +95,8 @@ public class AccountController : ControllerBase
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var account = await _db.Accounts.FirstOrDefaultAsync(a => a.Id == id);
|
var userId = User.Identity?.Name ?? "system";
|
||||||
if (account == null)
|
await _accountService.DeleteAccountAsync(id, userId);
|
||||||
return BadRequest(new Response { Status = "Error", Message = "Account not found." });
|
|
||||||
|
|
||||||
_db.Accounts.Remove(account);
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Ok(new DataResponse
|
return Ok(new DataResponse
|
||||||
{
|
{
|
||||||
|
|
@ -156,49 +118,28 @@ public class AccountController : ControllerBase
|
||||||
// GET: api/Account/GetAccountList?search=&page=&pageSize=
|
// GET: api/Account/GetAccountList?search=&page=&pageSize=
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
[HttpGet("GetAccountList")]
|
[HttpGet("GetAccountList")]
|
||||||
public IActionResult GetAccountList(string? search = "", int page = 1, int pageSize = 12)
|
public async Task<IActionResult> GetAccountList(string? search = "", int page = 1, int pageSize = 12)
|
||||||
{
|
{
|
||||||
search ??= "";
|
var pagedResult = await _accountService.GetAccountsPagedAsync(page, pageSize, search);
|
||||||
|
|
||||||
var query = _db.Accounts
|
var data = pagedResult.Items.Select(a => new
|
||||||
.Where(a => a.IsDeleted == false || a.IsDeleted == null);
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(search))
|
|
||||||
{
|
{
|
||||||
var s = search.ToLower();
|
Id = a.Id,
|
||||||
query = query.Where(a =>
|
Name = a.Name,
|
||||||
(a.Name ?? "").ToLower().Contains(s) ||
|
Type = a.Type ?? "",
|
||||||
(a.Email ?? "").ToLower().Contains(s) ||
|
Phone = a.Phone,
|
||||||
(a.Phone ?? "").Contains(s) ||
|
Email = a.Email,
|
||||||
(a.Website ?? "").ToLower().Contains(s)
|
Industry = (int?)null, // Map if needed
|
||||||
);
|
Website = a.Website
|
||||||
}
|
});
|
||||||
|
|
||||||
var totalCount = query.Count();
|
|
||||||
|
|
||||||
var data = query
|
|
||||||
.OrderByDescending(a => a.Id)
|
|
||||||
.Skip((page - 1) * pageSize)
|
|
||||||
.Take(pageSize)
|
|
||||||
.Select(a => new
|
|
||||||
{
|
|
||||||
a.Id,
|
|
||||||
a.Name,
|
|
||||||
a.Type,
|
|
||||||
a.Phone,
|
|
||||||
a.Email,
|
|
||||||
Industry = a.IndustryId,
|
|
||||||
a.Website
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var viewModel = new Pagination_DTO
|
var viewModel = new Pagination_DTO
|
||||||
{
|
{
|
||||||
Data = data,
|
Data = data,
|
||||||
PageNumber = page,
|
PageNumber = page,
|
||||||
PageSize = pageSize,
|
PageSize = pageSize,
|
||||||
TotalCount = totalCount,
|
TotalCount = pagedResult.TotalCount,
|
||||||
TotalPages = (int)Math.Ceiling(totalCount / (double)pageSize)
|
TotalPages = (int)Math.Ceiling(pagedResult.TotalCount / (double)pageSize)
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(viewModel);
|
return Ok(viewModel);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
|
||||||
namespace Api.SeaHavenIndustries.Controllers
|
namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
|
|
@ -13,12 +15,12 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
public class AssetController : Controller
|
public class AssetController : Controller
|
||||||
{
|
{
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
private readonly ApplicationDbContext _db;
|
private readonly IAssetService _assetService;
|
||||||
|
|
||||||
public AssetController(UserManager<ApplicationUser> userManager, ApplicationDbContext db)
|
public AssetController(UserManager<ApplicationUser> userManager, IAssetService assetService)
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_db = db;
|
_assetService = assetService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
|
|
@ -27,17 +29,15 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Assets model = new Assets();
|
var createDto = new CreateAssetDTO
|
||||||
model.AssetCode = asset.AssetCode;
|
{
|
||||||
model.Name = asset.Name;
|
Name = asset.Name ?? throw new ArgumentException("Name is required"),
|
||||||
model.Description = asset.Description;
|
LocationId = asset.LocationId
|
||||||
model.AccountId = asset.AccountId;
|
};
|
||||||
model.LocationId = asset.LocationId;
|
|
||||||
model.IsActive = asset.IsActive;
|
var userId = User.Identity?.Name ?? "system";
|
||||||
|
await _assetService.CreateAssetAsync(createDto, userId);
|
||||||
_db.Assets.Add(model);
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Ok(new DataResponse { Message = "Asset Created Successfully", Status = "200" });
|
return Ok(new DataResponse { Message = "Asset Created Successfully", Status = "200" });
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -52,23 +52,15 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var exist = _db.Assets.Where(w => w.Id == asset.Id).FirstOrDefault();
|
var updateDto = new UpdateAssetDTO
|
||||||
|
|
||||||
if (exist == null)
|
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = "Asset not found!" });
|
Name = asset.Name,
|
||||||
}
|
LocationId = asset.LocationId
|
||||||
|
};
|
||||||
|
|
||||||
|
var userId = User.Identity?.Name ?? "system";
|
||||||
|
await _assetService.UpdateAssetAsync(asset.Id, updateDto, userId);
|
||||||
|
|
||||||
exist.AssetCode = asset.AssetCode;
|
|
||||||
exist.Name = asset.Name;
|
|
||||||
exist.Description = asset.Description;
|
|
||||||
exist.AccountId = asset.AccountId;
|
|
||||||
exist.LocationId = asset.LocationId;
|
|
||||||
exist.IsActive = asset.IsActive;
|
|
||||||
|
|
||||||
_db.Assets.Update(exist);
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Ok(new DataResponse { Message = "Asset Updated Successfully", Status = "200" });
|
return Ok(new DataResponse { Message = "Asset Updated Successfully", Status = "200" });
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -83,18 +75,8 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var exist = _db.Assets.Where(w => w.Id == id).FirstOrDefault();
|
var userId = User.Identity?.Name ?? "system";
|
||||||
|
await _assetService.DeleteAssetAsync(id, userId);
|
||||||
if (exist != null)
|
|
||||||
{
|
|
||||||
_db.Remove(exist);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return BadRequest(new Response { Status = "Error", Message = "Asset not found!" });
|
|
||||||
}
|
|
||||||
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
return Ok(new DataResponse { Message = "Asset Deleted Successfully", Status = "200" });
|
return Ok(new DataResponse { Message = "Asset Deleted Successfully", Status = "200" });
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -109,17 +91,13 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var asset = await _db.Assets
|
var asset = await _assetService.GetAssetByIdWithDetailsAsync(id);
|
||||||
.Include(a => a.Account)
|
|
||||||
.Include(a => a.Location)
|
|
||||||
.Where(w => w.Id == id)
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
if (asset == null)
|
if (asset == null)
|
||||||
{
|
{
|
||||||
return NotFound(new Response { Status = "Error", Message = "Asset not found" });
|
return NotFound(new Response { Status = "Error", Message = "Asset not found" });
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(asset);
|
return Ok(asset);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -130,48 +108,25 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("GetAssetList")]
|
[Route("GetAssetList")]
|
||||||
public IActionResult GetAssetList(string? search = "", int page = 1, int pageSize = 10)
|
public async Task<IActionResult> GetAssetList(string? search = "", int page = 1, int pageSize = 10)
|
||||||
{
|
{
|
||||||
// Build the query with search filter
|
var pagedResult = await _assetService.GetAssetsPagedAsync(page, pageSize, search);
|
||||||
var query = _db.Assets
|
|
||||||
.Include(a => a.Account)
|
|
||||||
.Include(a => a.Location)
|
|
||||||
.Where(s =>
|
|
||||||
string.IsNullOrEmpty(search) ||
|
|
||||||
(s.Name != null && s.Name.ToLower().Contains(search.ToLower())) ||
|
|
||||||
(s.AssetCode != null && s.AssetCode.ToLower().Contains(search.ToLower())) ||
|
|
||||||
(s.Description != null && s.Description.ToLower().Contains(search.ToLower()))
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get total count AFTER applying search filter
|
var data = pagedResult.Items.Select(a => new
|
||||||
var totalCount = query.Count();
|
{
|
||||||
|
a.Id,
|
||||||
// Get paginated data
|
a.Name,
|
||||||
var data = query
|
LocationName = a.LocationName ?? "",
|
||||||
.Select(n => new
|
a.CreatedDate
|
||||||
{
|
});
|
||||||
n.Id,
|
|
||||||
n.AssetCode,
|
|
||||||
n.Name,
|
|
||||||
n.Description,
|
|
||||||
n.IsActive,
|
|
||||||
AccountName = n.Account != null ? n.Account.Name : "",
|
|
||||||
LocationName = n.Location != null ? n.Location.Name : ""
|
|
||||||
})
|
|
||||||
.OrderByDescending(d => d.Id)
|
|
||||||
.Skip((page - 1) * pageSize)
|
|
||||||
.Take(pageSize)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize);
|
|
||||||
|
|
||||||
var viewModel = new Pagination_DTO
|
var viewModel = new Pagination_DTO
|
||||||
{
|
{
|
||||||
Data = data,
|
Data = data,
|
||||||
PageNumber = page,
|
PageNumber = page,
|
||||||
PageSize = pageSize,
|
PageSize = pageSize,
|
||||||
TotalCount = totalCount,
|
TotalCount = pagedResult.TotalCount,
|
||||||
TotalPages = totalPages
|
TotalPages = (int)Math.Ceiling(pagedResult.TotalCount / (double)pageSize)
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(viewModel);
|
return Ok(viewModel);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using SendGrid.Helpers.Mail;
|
using SendGrid.Helpers.Mail;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
namespace Api.SeaHavenIndustries.Controllers
|
namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
|
|
@ -15,11 +16,17 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
public class ContactController : Controller
|
public class ContactController : Controller
|
||||||
{
|
{
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
private readonly ApplicationDbContext _db;
|
private readonly IContactService _contactService;
|
||||||
public ContactController(UserManager<ApplicationUser> userManager, ApplicationDbContext db)
|
private readonly ILocationService _locationService;
|
||||||
|
|
||||||
|
public ContactController(
|
||||||
|
UserManager<ApplicationUser> userManager,
|
||||||
|
IContactService contactService,
|
||||||
|
ILocationService locationService)
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_db = db;
|
_contactService = contactService;
|
||||||
|
_locationService = locationService;
|
||||||
}
|
}
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("AddContacts")]
|
[Route("AddContacts")]
|
||||||
|
|
@ -27,27 +34,10 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Contacts model = new Contacts();
|
// ✅ Use DTO mapping method instead of manual property assignment
|
||||||
model.Title = contacts.Title;
|
var userId = _userManager.GetUserId(User) ?? "system";
|
||||||
model.Owner = contacts.Owner;
|
await _contactService.CreateContactAsync(contacts.ToServiceCreateDTO(), userId);
|
||||||
model.FirstName = contacts.FirstName;
|
|
||||||
model.MiddleName = contacts.MiddleName;
|
|
||||||
model.LastName = contacts.LastName;
|
|
||||||
model.ContactType = contacts.ContactType;
|
|
||||||
model.PhoneNumber = contacts.PhoneNumber;
|
|
||||||
model.Email = contacts.Email;
|
|
||||||
model.Address1 = contacts.Address1;
|
|
||||||
model.Address2 = contacts.Address2;
|
|
||||||
model.City = contacts.City;
|
|
||||||
model.State = contacts.State;
|
|
||||||
model.Zip = contacts.Zip;
|
|
||||||
model.FacebookUrl = contacts.FacebookUrl;
|
|
||||||
model.LinkedInUrl = contacts.LinkedInUrl;
|
|
||||||
model.TwitterUrl = contacts.TwitterUrl;
|
|
||||||
model.LocationId = contacts.LocationId;
|
|
||||||
model.AccountId = contacts.AccountId;
|
|
||||||
_db.Contacts.Add(model);
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" });
|
return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" });
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -62,55 +52,39 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var exist = _db.Contacts.Where(w => w.Id == contacts.Id).FirstOrDefault();
|
// ✅ Use DTO mapping method instead of manual property assignment
|
||||||
if (exist == null)
|
var userId = _userManager.GetUserId(User) ?? "system";
|
||||||
return BadRequest(new Response { Status = "Error", Message = "Contact not found" });
|
await _contactService.UpdateContactAsync(contacts.Id, contacts.ToServiceUpdateDTO(), userId);
|
||||||
|
|
||||||
exist.Title = contacts.Title;
|
|
||||||
exist.Owner = contacts.Owner;
|
|
||||||
exist.FirstName = contacts.FirstName;
|
|
||||||
exist.MiddleName = contacts.MiddleName;
|
|
||||||
exist.LastName = contacts.LastName;
|
|
||||||
exist.ContactType = contacts.ContactType;
|
|
||||||
exist.PhoneNumber = contacts.PhoneNumber;
|
|
||||||
exist.Email = contacts.Email;
|
|
||||||
exist.Address1 = contacts.Address1;
|
|
||||||
exist.Address2 = contacts.Address2;
|
|
||||||
exist.City = contacts.City;
|
|
||||||
exist.State = contacts.State;
|
|
||||||
exist.Zip = contacts.Zip;
|
|
||||||
exist.FacebookUrl = contacts.FacebookUrl;
|
|
||||||
exist.LinkedInUrl = contacts.LinkedInUrl;
|
|
||||||
exist.TwitterUrl = contacts.TwitterUrl;
|
|
||||||
exist.LocationId = contacts.LocationId;
|
|
||||||
exist.AccountId = contacts.AccountId;
|
|
||||||
_db.Contacts.Update(exist);
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" });
|
return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" });
|
||||||
}
|
}
|
||||||
|
catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
return BadRequest(new Response { Status = "Error", Message = "Contact not found" });
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("DeleteContacts")]
|
[Route("DeleteContacts")]
|
||||||
public async Task<IActionResult> DeleteContacts(int id)
|
public async Task<IActionResult> DeleteContacts(int id)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var exist = _db.Contacts.Where(w => w.Id == id).FirstOrDefault();
|
var userId = _userManager.GetUserId(User) ?? "system";
|
||||||
if (exist != null)
|
|
||||||
{
|
// ✅ Call Service layer (not DataService directly)
|
||||||
_db.Remove(exist);
|
await _contactService.DeleteContactAsync(id, userId);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return BadRequest(new Response { Status = "Error", Message = "ID not matched!" });
|
|
||||||
}
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
return Ok(new DataResponse { Message = "Removed Successfully", Status = "200" });
|
return Ok(new DataResponse { Message = "Removed Successfully", Status = "200" });
|
||||||
}
|
}
|
||||||
|
catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
return BadRequest(new Response { Status = "Error", Message = "ID not matched!" });
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
||||||
|
|
@ -118,30 +92,21 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("GetContactList")]
|
[Route("GetContactList")]
|
||||||
public IActionResult GetContactList(string? search ="", int page = 1, int pageSize = 10)
|
public async Task<IActionResult> GetContactList(string? search ="", int page = 1, int pageSize = 10)
|
||||||
{
|
{
|
||||||
var totalCount = _db.Contacts.Count();
|
// ✅ Call Service layer
|
||||||
var data = _db.Contacts.Where(s=>
|
var pagedResult = await _contactService.GetContactsPagedAsync(page, pageSize, search);
|
||||||
(s.FirstName != null && s.FirstName.ToLower().Contains(search.ToLower())) ||
|
|
||||||
(s.LastName != null && s.LastName.ToLower().Contains(search.ToLower())) ||
|
// ✅ Use DTO mapping method (NO manual transformation in controller)
|
||||||
(s.Email != null && s.Email.ToLower().Contains(search.ToLower())) ||
|
var data = ContactListItem_DTO.FromServiceDTOs(pagedResult.Items);
|
||||||
(s.PhoneNumber != null && s.PhoneNumber.Contains(search.ToLower()))
|
var totalPages = (int)Math.Ceiling(pagedResult.TotalCount / (double)pageSize);
|
||||||
).Select(n => new
|
|
||||||
{
|
|
||||||
n.Id,
|
|
||||||
Name = (n.FirstName + " " + n.LastName).Trim(),
|
|
||||||
email = n.Email,
|
|
||||||
phone = n.PhoneNumber
|
|
||||||
}).OrderByDescending(d => d.Id).Skip((page - 1) * pageSize)
|
|
||||||
.Take(pageSize).ToList();
|
|
||||||
var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize);
|
|
||||||
|
|
||||||
var viewModel = new Pagination_DTO
|
var viewModel = new Pagination_DTO
|
||||||
{
|
{
|
||||||
Data = data,
|
Data = data,
|
||||||
PageNumber = page,
|
PageNumber = page,
|
||||||
PageSize = pageSize,
|
PageSize = pageSize,
|
||||||
TotalCount = totalCount,
|
TotalCount = pagedResult.TotalCount,
|
||||||
TotalPages = totalPages
|
TotalPages = totalPages
|
||||||
};
|
};
|
||||||
return Ok(viewModel);
|
return Ok(viewModel);
|
||||||
|
|
@ -151,52 +116,54 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
[Route("GetContacts")]
|
[Route("GetContacts")]
|
||||||
public async Task<IActionResult> GetContacts()
|
public async Task<IActionResult> GetContacts()
|
||||||
{
|
{
|
||||||
var data = await _db.Contacts.ToListAsync();
|
// ✅ Call Service layer
|
||||||
|
var data = await _contactService.GetAllContactsAsync();
|
||||||
return Ok(data);
|
return Ok(data);
|
||||||
}
|
}
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("GetLocations")]
|
[Route("GetLocations")]
|
||||||
public async Task<IActionResult> GetLocations()
|
public async Task<IActionResult> GetLocations()
|
||||||
{
|
{
|
||||||
var data = await _db.Locations.Select(s => new LocationViewModel
|
// ✅ Call Service layer
|
||||||
{
|
var locations = await _locationService.GetAllLocationsAsync();
|
||||||
Id = s.Id,
|
|
||||||
Name = s.Title + " - " + s.Name
|
// ✅ Use DTO mapping method (NO manual transformation in controller)
|
||||||
}).ToListAsync();
|
var data = LocationViewModel_DTO.FromServiceDTOs(locations);
|
||||||
return Ok(data);
|
return Ok(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: ARCHITECTURAL VIOLATION - These methods should NOT be in ContactController
|
||||||
|
// GetCategories should be in a CategoryController with ICategoryService
|
||||||
|
// GetUsers should be in a UserController with IUserService
|
||||||
|
// For now, commenting out to prevent direct database access
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("GetCategories")]
|
[Route("GetCategories")]
|
||||||
public async Task<IActionResult> GetCategories()
|
public async Task<IActionResult> GetCategories()
|
||||||
{
|
{
|
||||||
var data = await _db.Categories.ToListAsync();
|
// ❌ TEMPORARY: Needs ICategoryService
|
||||||
return Ok(data);
|
return StatusCode(501, new Response { Status = "Error", Message = "Not Implemented - Needs CategoryService" });
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("GetUsers")]
|
[Route("GetUsers")]
|
||||||
public async Task<IActionResult> GetUsers()
|
public async Task<IActionResult> GetUsers()
|
||||||
{
|
{
|
||||||
var filteredUsers = await (from user in _db.Users
|
// ❌ TEMPORARY: Needs IUserService
|
||||||
where !(from userRole in _db.UserRoles
|
return StatusCode(501, new Response { Status = "Error", Message = "Not Implemented - Needs UserService" });
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
// TODO: ARCHITECTURAL VIOLATION - Location CRUD methods should NOT be in ContactController
|
||||||
|
// These should be in LocationController with ILocationService
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("AddLocation")]
|
[Route("AddLocation")]
|
||||||
public async Task<IActionResult> AddLocation(Location_DTO model)
|
public async Task<IActionResult> AddLocation(Location_DTO model)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Locations locations = new Locations();
|
// ✅ Use Service layer with DTO mapping
|
||||||
locations.Title = model.Title;
|
var userId = _userManager.GetUserId(User) ?? "system";
|
||||||
locations.Name = model.Name;
|
await _locationService.CreateLocationAsync(model.ToServiceCreateDTO(), userId);
|
||||||
_db.Locations.Add(locations);
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" });
|
return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" });
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -204,26 +171,22 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("EditLocation")]
|
[Route("EditLocation")]
|
||||||
public async Task<IActionResult> EditLocation(EditLocation_DTO model)
|
public async Task<IActionResult> EditLocation(EditLocation_DTO model)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var exist = _db.Locations.Where(w => w.Id == model.Id).FirstOrDefault();
|
// ✅ Use Service layer with DTO mapping
|
||||||
if (exist != null)
|
var userId = _userManager.GetUserId(User) ?? "system";
|
||||||
{
|
await _locationService.UpdateLocationAsync(model.Id, model.ToServiceUpdateDTO(), userId);
|
||||||
exist.Title = model.Title;
|
|
||||||
exist.Name = model.Name;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return BadRequest(new Response { Status = "Error", Message = "ID not matched!" });
|
|
||||||
}
|
|
||||||
_db.Locations.Update(exist);
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" });
|
return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" });
|
||||||
}
|
}
|
||||||
|
catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
return BadRequest(new Response { Status = "Error", Message = "ID not matched!" });
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
||||||
|
|
@ -236,20 +199,15 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var data1 = await _db.Templates.ToListAsync();
|
// ✅ Use Service layer
|
||||||
_db.Templates.RemoveRange(data1);
|
var userId = _userManager.GetUserId(User) ?? "system";
|
||||||
var data = await _db.Locations.Where(w => w.Id == Id).FirstOrDefaultAsync();
|
await _locationService.DeleteLocationAsync(Id, userId);
|
||||||
if (data != null)
|
|
||||||
{
|
|
||||||
_db.Locations.Remove(data ?? new Locations());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return BadRequest(new Response { Status = "Error", Message = "ID not matched!" });
|
|
||||||
}
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" });
|
return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" });
|
||||||
}
|
}
|
||||||
|
catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
return BadRequest(new Response { Status = "Error", Message = "ID not matched!" });
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
||||||
|
|
@ -258,34 +216,25 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("GetAddressbook")]
|
[Route("GetAddressbook")]
|
||||||
public IActionResult GetAddressbook(string? search = "", int page = 1, int pageSize = 10)
|
public async Task<IActionResult> GetAddressbook(string? search = "", int page = 1, int pageSize = 10)
|
||||||
{
|
{
|
||||||
var totalCount = _db.Locations.Count();
|
// ✅ Call Service layer
|
||||||
var data = _db.Locations.Where(w=> (w.Name ?? "").ToLower().Contains(search.ToLower()) || (w.Title ?? "").ToLower().Contains(search.ToLower())).Select(n => new
|
var pagedResult = await _locationService.GetLocationsPagedAsync(page, pageSize, search);
|
||||||
{
|
|
||||||
n.Id,
|
// ✅ Use DTO mapping method (NO manual transformation in controller)
|
||||||
n.Name,
|
var data = LocationListItem_DTO.FromServiceDTOs(pagedResult.Items);
|
||||||
n.Title
|
var totalPages = (int)Math.Ceiling(pagedResult.TotalCount / (double)pageSize);
|
||||||
}).OrderByDescending(d => d.Id).Skip((page - 1) * pageSize)
|
|
||||||
.Take(pageSize).ToList();
|
|
||||||
var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize);
|
|
||||||
|
|
||||||
var viewModel = new Pagination_DTO
|
var viewModel = new Pagination_DTO
|
||||||
{
|
{
|
||||||
Data = data,
|
Data = data,
|
||||||
PageNumber = page,
|
PageNumber = page,
|
||||||
PageSize = pageSize,
|
PageSize = pageSize,
|
||||||
TotalCount = totalCount,
|
TotalCount = pagedResult.TotalCount,
|
||||||
TotalPages = totalPages
|
TotalPages = totalPages
|
||||||
};
|
};
|
||||||
return Ok(viewModel);
|
return Ok(viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LocationViewModel
|
|
||||||
{
|
|
||||||
public int? Id { get; set; }
|
|
||||||
public string? Name { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ using Data.SeaHavenIndustries;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
|
||||||
namespace Api.SeaHavenIndustries.Controllers
|
namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
|
|
@ -11,10 +13,12 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
[Route("api/dispatches")]
|
[Route("api/dispatches")]
|
||||||
public class DispatchController : Controller
|
public class DispatchController : Controller
|
||||||
{
|
{
|
||||||
private readonly ApplicationDbContext _db;
|
private readonly IDispatchService _dispatchService;
|
||||||
|
private readonly ApplicationDbContext _db; // Keep for complex queries
|
||||||
|
|
||||||
public DispatchController(ApplicationDbContext db)
|
public DispatchController(IDispatchService dispatchService, ApplicationDbContext db)
|
||||||
{
|
{
|
||||||
|
_dispatchService = dispatchService;
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,19 @@
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/Employee")]
|
[Route("api/Employee")]
|
||||||
[Route("api/employees")]
|
[Route("api/employees")]
|
||||||
public class EmployeeController : Controller
|
public class EmployeeController : Controller
|
||||||
{
|
{
|
||||||
private readonly ApplicationDbContext _db;
|
private readonly IEmployeeService _employeeService;
|
||||||
|
|
||||||
public EmployeeController(ApplicationDbContext db)
|
public EmployeeController(IEmployeeService employeeService)
|
||||||
{
|
{
|
||||||
_db = db;
|
_employeeService = employeeService;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
|
|
@ -21,42 +23,27 @@ public class EmployeeController : Controller
|
||||||
[HttpPost("AddEmployees")]
|
[HttpPost("AddEmployees")]
|
||||||
public async Task<IActionResult> AddEmployees(AddEmployee_DTO dto)
|
public async Task<IActionResult> AddEmployees(AddEmployee_DTO dto)
|
||||||
{
|
{
|
||||||
var employee = new Employee
|
try
|
||||||
{
|
{
|
||||||
FirstName = dto.FirstName,
|
var createDto = new CreateEmployeeDTO
|
||||||
LastName = dto.LastName,
|
|
||||||
JobTitleId = dto.JobTitleId,
|
|
||||||
PermissionGroupId = dto.PermissionGroupId,
|
|
||||||
Status = dto.Status,
|
|
||||||
LastLogin = dto.LastLogin,
|
|
||||||
CreatedDate = DateTime.UtcNow
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(dto.Email))
|
|
||||||
{
|
|
||||||
employee.Emails.Add(new EmployeeEmail
|
|
||||||
{
|
{
|
||||||
Address = dto.Email,
|
FirstName = dto.FirstName,
|
||||||
IsPrimary = true,
|
LastName = dto.LastName,
|
||||||
EmailTypeId = 1
|
JobTitleId = dto.JobTitleId,
|
||||||
});
|
DepartmentId = null, // Map from PermissionGroupId if needed
|
||||||
}
|
Email = dto.Email,
|
||||||
|
Phone = dto.Phone
|
||||||
|
};
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(dto.Phone))
|
var userId = User.Identity?.Name ?? "system";
|
||||||
|
await _employeeService.CreateEmployeeAsync(createDto, userId);
|
||||||
|
|
||||||
|
return Ok(new { Message = "Employee added successfully" });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
employee.Phones.Add(new EmployeePhone
|
return BadRequest(new { Message = ex.Message });
|
||||||
{
|
|
||||||
Number = dto.Phone,
|
|
||||||
Extension = dto.PhoneExtension,
|
|
||||||
IsPrimary = true,
|
|
||||||
PhoneTypeId = 1
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_db.Employees.Add(employee);
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Ok(new { Message = "Employee added successfully" });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
|
|
@ -65,87 +52,54 @@ public class EmployeeController : Controller
|
||||||
[HttpPost("EditEmployees")]
|
[HttpPost("EditEmployees")]
|
||||||
public async Task<IActionResult> EditEmployees(EditEmployee_DTO dto)
|
public async Task<IActionResult> EditEmployees(EditEmployee_DTO dto)
|
||||||
{
|
{
|
||||||
var employee = await _db.Employees
|
try
|
||||||
.Include(e => e.Emails)
|
{
|
||||||
.Include(e => e.Phones)
|
var updateDto = new UpdateEmployeeDTO
|
||||||
.FirstOrDefaultAsync(e => e.Id == dto.Id);
|
{
|
||||||
|
FirstName = dto.FirstName,
|
||||||
|
LastName = dto.LastName,
|
||||||
|
JobTitleId = dto.JobTitleId
|
||||||
|
};
|
||||||
|
|
||||||
if (employee == null)
|
var userId = User.Identity?.Name ?? "system";
|
||||||
return BadRequest("Employee not found");
|
await _employeeService.UpdateEmployeeAsync(dto.Id, updateDto, userId);
|
||||||
|
|
||||||
employee.FirstName = dto.FirstName;
|
return Ok(new { Message = "Employee updated successfully" });
|
||||||
employee.LastName = dto.LastName;
|
}
|
||||||
employee.JobTitleId = dto.JobTitleId;
|
catch (Exception ex)
|
||||||
employee.PermissionGroupId = dto.PermissionGroupId;
|
{
|
||||||
employee.Status = dto.Status;
|
return BadRequest(new { Message = ex.Message });
|
||||||
employee.LastLogin = dto.LastLogin;
|
}
|
||||||
employee.LastModificationTime = DateTime.UtcNow;
|
|
||||||
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
return Ok(new { Message = "Employee updated successfully" });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
// GET: api/Employee/GetEmployeeList
|
// GET: api/Employee/GetEmployeeList
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
[HttpGet("GetEmployeeList")]
|
[HttpGet("GetEmployeeList")]
|
||||||
public IActionResult GetEmployeeList(string? search = "", int page = 1, int pageSize = 12)
|
public async Task<IActionResult> GetEmployeeList(string? search = "", int page = 1, int pageSize = 12)
|
||||||
{
|
{
|
||||||
search ??= "";
|
var pagedResult = await _employeeService.GetEmployeesPagedAsync(page, pageSize, search);
|
||||||
|
|
||||||
var totalCount = _db.Employees.Where(e => !e.IsDeleted.HasValue || e.IsDeleted == false).Count();
|
var data = pagedResult.Items.Select(e => new
|
||||||
|
{
|
||||||
|
id = e.Id,
|
||||||
|
firstName = e.FirstName,
|
||||||
|
lastName = e.LastName,
|
||||||
|
jobTitle = e.JobTitleName ?? "",
|
||||||
|
email = e.Email ?? "",
|
||||||
|
phone = e.Phone ?? "",
|
||||||
|
department = e.DepartmentName ?? "",
|
||||||
|
status = "Active" // Map from employee status if available
|
||||||
|
});
|
||||||
|
|
||||||
var data = _db.Employees
|
var totalPages = (int)Math.Ceiling(pagedResult.TotalCount / (double)pageSize);
|
||||||
.Include(e => e.JobTitle)
|
|
||||||
.Include(e => e.Department)
|
|
||||||
.Include(e => e.Emails)
|
|
||||||
.Include(e => e.Phones)
|
|
||||||
.Where(e => !e.IsDeleted.HasValue || e.IsDeleted == false)
|
|
||||||
.Where(e =>
|
|
||||||
string.IsNullOrWhiteSpace(search) ||
|
|
||||||
(e.FirstName != null && e.FirstName.ToLower().Contains(search.ToLower())) ||
|
|
||||||
(e.LastName != null && e.LastName.ToLower().Contains(search.ToLower())) ||
|
|
||||||
e.Emails.Any(x => x.Address != null && x.Address.ToLower().Contains(search.ToLower())) ||
|
|
||||||
e.Phones.Any(x => x.Number != null && x.Number.Contains(search))
|
|
||||||
)
|
|
||||||
.Select(e => new
|
|
||||||
{
|
|
||||||
e.Id,
|
|
||||||
e.FirstName,
|
|
||||||
e.LastName,
|
|
||||||
JobTitleName = e.JobTitle != null ? e.JobTitle.Name : "",
|
|
||||||
DepartmentName = e.Department != null ? e.Department.Name : "",
|
|
||||||
e.Status,
|
|
||||||
PrimaryEmail = e.Emails.Where(x => x.IsPrimary == true).Select(x => x.Address).FirstOrDefault(),
|
|
||||||
PrimaryPhone = e.Phones.Where(x => x.IsPrimary == true).Select(x => x.Number).FirstOrDefault(),
|
|
||||||
PhoneExtension = e.Phones.Where(x => x.IsPrimary == true).Select(x => x.Extension).FirstOrDefault()
|
|
||||||
})
|
|
||||||
.OrderByDescending(e => e.Id)
|
|
||||||
.ToList()
|
|
||||||
.Skip((page - 1) * pageSize)
|
|
||||||
.Take(pageSize)
|
|
||||||
.Select(e => new
|
|
||||||
{
|
|
||||||
id = e.Id,
|
|
||||||
firstName = e.FirstName,
|
|
||||||
lastName = e.LastName,
|
|
||||||
jobTitle = e.JobTitleName ?? "",
|
|
||||||
email = e.PrimaryEmail ?? "",
|
|
||||||
phone = e.PrimaryPhone != null
|
|
||||||
? e.PrimaryPhone + (e.PhoneExtension != null ? " ext. " + e.PhoneExtension : "")
|
|
||||||
: "",
|
|
||||||
department = e.DepartmentName ?? "",
|
|
||||||
status = e.Status
|
|
||||||
});
|
|
||||||
|
|
||||||
var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize);
|
|
||||||
|
|
||||||
var viewModel = new Pagination_DTO
|
var viewModel = new Pagination_DTO
|
||||||
{
|
{
|
||||||
Data = data,
|
Data = data,
|
||||||
PageNumber = page,
|
PageNumber = page,
|
||||||
PageSize = pageSize,
|
PageSize = pageSize,
|
||||||
TotalCount = totalCount,
|
TotalCount = pagedResult.TotalCount,
|
||||||
TotalPages = totalPages
|
TotalPages = totalPages
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -159,18 +113,8 @@ public class EmployeeController : Controller
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var employee = await _db.Employees
|
var userId = User.Identity?.Name ?? "system";
|
||||||
.FirstOrDefaultAsync(e => e.Id == id);
|
await _employeeService.DeleteEmployeeAsync(id, userId);
|
||||||
|
|
||||||
if (employee == null)
|
|
||||||
return BadRequest(new Response
|
|
||||||
{
|
|
||||||
Status = "Error",
|
|
||||||
Message = "Employee not found."
|
|
||||||
});
|
|
||||||
|
|
||||||
_db.Employees.Remove(employee);
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Ok(new DataResponse
|
return Ok(new DataResponse
|
||||||
{
|
{
|
||||||
|
|
@ -178,6 +122,14 @@ public class EmployeeController : Controller
|
||||||
Status = "200"
|
Status = "200"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
return BadRequest(new Response
|
||||||
|
{
|
||||||
|
Status = "Error",
|
||||||
|
Message = ex.Message
|
||||||
|
});
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response
|
return BadRequest(new Response
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,9 @@ using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
using SeaHaven.DataServices.Interfaces;
|
||||||
|
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
|
|
@ -12,11 +15,15 @@ using Microsoft.EntityFrameworkCore;
|
||||||
[Route("api/followups")]
|
[Route("api/followups")]
|
||||||
public class FollowUpController : ControllerBase
|
public class FollowUpController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ApplicationDbContext _db;
|
private readonly IFollowUpService _followUpService;
|
||||||
|
private readonly IFollowUpDataService _followUpDataService; // Keep for direct entity operations
|
||||||
|
private readonly ApplicationDbContext _db; // Keep for User lookups
|
||||||
private readonly UserManager<ApplicationUser> _users;
|
private readonly UserManager<ApplicationUser> _users;
|
||||||
|
|
||||||
public FollowUpController(ApplicationDbContext db, UserManager<ApplicationUser> users)
|
public FollowUpController(IFollowUpService followUpService, IFollowUpDataService followUpDataService, ApplicationDbContext db, UserManager<ApplicationUser> users)
|
||||||
{
|
{
|
||||||
|
_followUpService = followUpService;
|
||||||
|
_followUpDataService = followUpDataService;
|
||||||
_db = db;
|
_db = db;
|
||||||
_users = users;
|
_users = users;
|
||||||
}
|
}
|
||||||
|
|
@ -30,55 +37,28 @@ public class FollowUpController : ControllerBase
|
||||||
{
|
{
|
||||||
status = string.IsNullOrWhiteSpace(status) ? "Open" : status;
|
status = string.IsNullOrWhiteSpace(status) ? "Open" : status;
|
||||||
|
|
||||||
var query = _db.FollowUps
|
var pagedResult = await _followUpService.GetFollowUpsPagedAsync(page, pageSize, search, status);
|
||||||
.Include(x => x.Employee)
|
var items = pagedResult.Items;
|
||||||
.Include(x => x.Account)
|
|
||||||
.Include(x => x.Location)
|
|
||||||
.Include(x => x.WorkOrder)
|
|
||||||
.Where(x => x.Status == status);
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(search))
|
var rows = items.Select(x => new
|
||||||
{
|
{
|
||||||
var s = search.ToLower();
|
Id = x.Id,
|
||||||
|
Reason = x.Reason,
|
||||||
query = query.Where(x =>
|
ScheduleDate = x.ScheduleDate,
|
||||||
(x.Reason ?? "").ToLower().Contains(s) ||
|
ScheduleStartTime = x.ScheduleStartTime,
|
||||||
(x.Account != null && (x.Account.Name ?? "").ToLower().Contains(s)) ||
|
EmployeeId = x.EmployeeId,
|
||||||
(x.Employee != null &&
|
WorkOrderId = x.WorkOrderId,
|
||||||
(((x.Employee.FirstName ?? "") + " " + (x.Employee.LastName ?? ""))
|
AccountId = x.AccountId,
|
||||||
.ToLower().Contains(s))
|
LocationId = x.LocationId,
|
||||||
)
|
AccountName = x.AccountName ?? "",
|
||||||
);
|
AssignedTo = x.EmployeeName ?? "",
|
||||||
}
|
LocationName = x.LocationName ?? "",
|
||||||
|
WorkOrderNumber = "",
|
||||||
var totalCount = await query.CountAsync();
|
InternalWONumber = "",
|
||||||
|
Status = x.Status,
|
||||||
var rows = await query
|
CreatedDate = x.CreatedDate,
|
||||||
.OrderByDescending(x => x.Id)
|
CreatedById = (string?)null
|
||||||
.Skip((page - 1) * pageSize)
|
}).ToList();
|
||||||
.Take(pageSize)
|
|
||||||
.Select(x => new
|
|
||||||
{
|
|
||||||
x.Id,
|
|
||||||
x.Reason,
|
|
||||||
x.ScheduleDate,
|
|
||||||
x.ScheduleStartTime,
|
|
||||||
x.EmployeeId,
|
|
||||||
x.WorkOrderId,
|
|
||||||
x.AccountId,
|
|
||||||
x.LocationId,
|
|
||||||
AccountName = x.Account != null ? x.Account.Name : "",
|
|
||||||
AssignedTo = x.Employee != null
|
|
||||||
? (x.Employee.FirstName + " " + x.Employee.LastName)
|
|
||||||
: "",
|
|
||||||
LocationName = x.Location != null ? x.Location.Name : "",
|
|
||||||
WorkOrderNumber = x.WorkOrder != null ? x.WorkOrder.WorkerOrderNumber : "",
|
|
||||||
InternalWONumber = x.WorkOrder != null ? x.WorkOrder.InternalWONumber : "",
|
|
||||||
x.Status,
|
|
||||||
x.CreatedDate,
|
|
||||||
CreatedById = x.createdby
|
|
||||||
})
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
var creatorIds = rows
|
var creatorIds = rows
|
||||||
.Select(r => r.CreatedById)
|
.Select(r => r.CreatedById)
|
||||||
|
|
@ -124,20 +104,15 @@ public class FollowUpController : ControllerBase
|
||||||
Data = data,
|
Data = data,
|
||||||
PageNumber = page,
|
PageNumber = page,
|
||||||
PageSize = pageSize,
|
PageSize = pageSize,
|
||||||
TotalCount = totalCount,
|
TotalCount = pagedResult.TotalCount,
|
||||||
TotalPages = (int)Math.Ceiling(totalCount / (double)pageSize)
|
TotalPages = (int)Math.Ceiling(pagedResult.TotalCount / (double)pageSize)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("GetById")]
|
[HttpGet("GetById")]
|
||||||
public async Task<IActionResult> GetById(int id)
|
public async Task<IActionResult> GetById(int id)
|
||||||
{
|
{
|
||||||
var model = await _db.FollowUps
|
var model = await _followUpDataService.GetByIdWithDetailsAsync(id);
|
||||||
.Include(x => x.Employee)
|
|
||||||
.Include(x => x.Account)
|
|
||||||
.Include(x => x.Location)
|
|
||||||
.Include(x => x.WorkOrder)
|
|
||||||
.FirstOrDefaultAsync(x => x.Id == id);
|
|
||||||
|
|
||||||
if (model == null) return NotFound();
|
if (model == null) return NotFound();
|
||||||
|
|
||||||
|
|
@ -198,8 +173,7 @@ public class FollowUpController : ControllerBase
|
||||||
createdby = userId
|
createdby = userId
|
||||||
};
|
};
|
||||||
|
|
||||||
_db.FollowUps.Add(model);
|
await _followUpDataService.AddAsync(model);
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Ok(new DataResponse { Status = "200", Message = "Follow Up created", Data = model.Id });
|
return Ok(new DataResponse { Status = "200", Message = "Follow Up created", Data = model.Id });
|
||||||
}
|
}
|
||||||
|
|
@ -207,7 +181,7 @@ public class FollowUpController : ControllerBase
|
||||||
[HttpPost("Update")]
|
[HttpPost("Update")]
|
||||||
public async Task<IActionResult> Update(FollowUp_DTO dto)
|
public async Task<IActionResult> Update(FollowUp_DTO dto)
|
||||||
{
|
{
|
||||||
var model = await _db.FollowUps.FindAsync(dto.Id);
|
var model = await _followUpDataService.GetByIdAsync(dto.Id);
|
||||||
if (model == null) return NotFound();
|
if (model == null) return NotFound();
|
||||||
|
|
||||||
model.Reason = dto.Reason;
|
model.Reason = dto.Reason;
|
||||||
|
|
@ -219,19 +193,19 @@ public class FollowUpController : ControllerBase
|
||||||
model.LocationId = dto.LocationId;
|
model.LocationId = dto.LocationId;
|
||||||
model.LastModificationTime = DateTime.UtcNow;
|
model.LastModificationTime = DateTime.UtcNow;
|
||||||
|
|
||||||
await _db.SaveChangesAsync();
|
await _followUpDataService.UpdateAsync(model);
|
||||||
return Ok(new DataResponse { Status = "200", Message = "Follow Up updated" });
|
return Ok(new DataResponse { Status = "200", Message = "Follow Up updated" });
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("Complete")]
|
[HttpPost("Complete")]
|
||||||
public async Task<IActionResult> Complete(int id)
|
public async Task<IActionResult> Complete(int id)
|
||||||
{
|
{
|
||||||
var model = await _db.FollowUps.FindAsync(id);
|
var model = await _followUpDataService.GetByIdAsync(id);
|
||||||
if (model == null) return NotFound();
|
if (model == null) return NotFound();
|
||||||
|
|
||||||
model.Status = "Completed";
|
model.Status = "Completed";
|
||||||
model.LastModificationTime = DateTime.UtcNow;
|
model.LastModificationTime = DateTime.UtcNow;
|
||||||
await _db.SaveChangesAsync();
|
await _followUpDataService.UpdateAsync(model);
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
@ -239,12 +213,12 @@ public class FollowUpController : ControllerBase
|
||||||
[HttpPost("Cancel")]
|
[HttpPost("Cancel")]
|
||||||
public async Task<IActionResult> Cancel(int id)
|
public async Task<IActionResult> Cancel(int id)
|
||||||
{
|
{
|
||||||
var model = await _db.FollowUps.FindAsync(id);
|
var model = await _followUpDataService.GetByIdAsync(id);
|
||||||
if (model == null) return NotFound();
|
if (model == null) return NotFound();
|
||||||
|
|
||||||
model.Status = "Cancelled";
|
model.Status = "Cancelled";
|
||||||
model.LastModificationTime = DateTime.UtcNow;
|
model.LastModificationTime = DateTime.UtcNow;
|
||||||
await _db.SaveChangesAsync();
|
await _followUpDataService.UpdateAsync(model);
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
@ -252,11 +226,10 @@ public class FollowUpController : ControllerBase
|
||||||
[HttpPost("Delete")]
|
[HttpPost("Delete")]
|
||||||
public async Task<IActionResult> Delete(int id)
|
public async Task<IActionResult> Delete(int id)
|
||||||
{
|
{
|
||||||
var model = await _db.FollowUps.FindAsync(id);
|
var model = await _followUpDataService.GetByIdAsync(id);
|
||||||
if (model == null) return NotFound();
|
if (model == null) return NotFound();
|
||||||
|
|
||||||
_db.FollowUps.Remove(model);
|
await _followUpDataService.DeleteAsync(id);
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Ok(new DataResponse { Status = "200", Message = "Follow Up deleted" });
|
return Ok(new DataResponse { Status = "200", Message = "Follow Up deleted" });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@ using Data.SeaHavenIndustries;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
using SeaHaven.DataServices.Interfaces;
|
||||||
|
|
||||||
namespace Api.SeaHavenIndustries.Controllers
|
namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
|
|
@ -12,60 +15,44 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
[Route("api/locations")]
|
[Route("api/locations")]
|
||||||
public class LocationController : Controller
|
public class LocationController : Controller
|
||||||
{
|
{
|
||||||
private readonly ApplicationDbContext _db;
|
private readonly ILocationService _locationService;
|
||||||
|
private readonly ILocationDataService _locationDataService; // Keep for direct entity operations
|
||||||
|
|
||||||
public LocationController(ApplicationDbContext db)
|
public LocationController(ILocationService locationService, ILocationDataService locationDataService)
|
||||||
{
|
{
|
||||||
_db = db;
|
_locationService = locationService;
|
||||||
|
_locationDataService = locationDataService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("GetLocationList")]
|
[HttpGet("GetLocationList")]
|
||||||
public IActionResult GetLocationList(string? search = "", int page = 1, int pageSize = 10)
|
public async Task<IActionResult> GetLocationList(string? search = "", int page = 1, int pageSize = 10)
|
||||||
{
|
{
|
||||||
var query = _db.Locations.AsQueryable();
|
var pagedResult = await _locationService.GetLocationsPagedAsync(page, pageSize, search);
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(search))
|
var data = pagedResult.Items.Select(l => new
|
||||||
{
|
{
|
||||||
var s = search.ToLower();
|
Id = l.Id,
|
||||||
query = query.Where(l =>
|
Name = l.Name,
|
||||||
(l.Name ?? "").ToLower().Contains(s) ||
|
Title = l.Title,
|
||||||
(l.Title ?? "").ToLower().Contains(s) ||
|
Address = l.Address1,
|
||||||
(l.Address1 ?? "").ToLower().Contains(s) ||
|
Address1 = l.Address1,
|
||||||
(l.City ?? "").ToLower().Contains(s));
|
Address2 = l.Address2,
|
||||||
}
|
City = l.City,
|
||||||
|
State = l.State,
|
||||||
var totalCount = query.Count();
|
ZipCode = l.Zip,
|
||||||
|
Phone = l.PhoneNumber,
|
||||||
var data = query
|
Contact = (string?)null,
|
||||||
.OrderByDescending(l => l.Id)
|
ContactEmail = l.Email,
|
||||||
.Skip((page - 1) * pageSize)
|
Status = l.Status
|
||||||
.Take(pageSize)
|
});
|
||||||
.Select(l => new
|
|
||||||
{
|
|
||||||
l.Id,
|
|
||||||
l.Name,
|
|
||||||
l.Title,
|
|
||||||
Address = l.Address1, // Database has Address1, not Address
|
|
||||||
l.Address1,
|
|
||||||
l.Address2,
|
|
||||||
l.City,
|
|
||||||
l.State,
|
|
||||||
ZipCode = l.Zip, // Database has Zip, not ZipCode
|
|
||||||
Phone = l.PhoneNumber, // Database has PhoneNumber, not Phone
|
|
||||||
Contact = (string?)null, // Contact column doesn't exist in database
|
|
||||||
ContactEmail = l.Email, // Database has Email, not ContactEmail
|
|
||||||
l.Status
|
|
||||||
// AccountId doesn't exist in database
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var viewModel = new Pagination_DTO
|
var viewModel = new Pagination_DTO
|
||||||
{
|
{
|
||||||
Data = data,
|
Data = data,
|
||||||
PageNumber = page,
|
PageNumber = page,
|
||||||
PageSize = pageSize,
|
PageSize = pageSize,
|
||||||
TotalCount = totalCount,
|
TotalCount = pagedResult.TotalCount,
|
||||||
TotalPages = (int)Math.Ceiling(totalCount / (double)pageSize)
|
TotalPages = (int)Math.Ceiling(pagedResult.TotalCount / (double)pageSize)
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(viewModel);
|
return Ok(viewModel);
|
||||||
|
|
@ -74,31 +61,29 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public async Task<IActionResult> GetLocationById(int id)
|
public async Task<IActionResult> GetLocationById(int id)
|
||||||
{
|
{
|
||||||
var location = await _db.Locations
|
var location = await _locationDataService.GetByIdAsync(id);
|
||||||
.Where(l => l.Id == id)
|
|
||||||
.Select(l => new
|
|
||||||
{
|
|
||||||
l.Id,
|
|
||||||
l.Name,
|
|
||||||
l.Title,
|
|
||||||
Address = l.Address1, // Database has Address1
|
|
||||||
l.Address1,
|
|
||||||
l.Address2,
|
|
||||||
l.City,
|
|
||||||
l.State,
|
|
||||||
ZipCode = l.Zip, // Database has Zip
|
|
||||||
Phone = l.PhoneNumber, // Database has PhoneNumber
|
|
||||||
Contact = (string?)null, // Contact doesn't exist
|
|
||||||
ContactEmail = l.Email, // Database has Email
|
|
||||||
l.Status
|
|
||||||
// AccountId doesn't exist
|
|
||||||
})
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
if (location == null)
|
if (location == null)
|
||||||
return NotFound(new Response { Status = "Error", Message = "Location not found" });
|
return NotFound(new Response { Status = "Error", Message = "Location not found" });
|
||||||
|
|
||||||
return Ok(location);
|
var result = new
|
||||||
|
{
|
||||||
|
location.Id,
|
||||||
|
location.Name,
|
||||||
|
location.Title,
|
||||||
|
Address = location.Address1,
|
||||||
|
location.Address1,
|
||||||
|
location.Address2,
|
||||||
|
location.City,
|
||||||
|
location.State,
|
||||||
|
ZipCode = location.Zip,
|
||||||
|
Phone = location.PhoneNumber,
|
||||||
|
Contact = (string?)null,
|
||||||
|
ContactEmail = location.Email,
|
||||||
|
location.Status
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
|
|
@ -110,19 +95,17 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
Name = model.Name,
|
Name = model.Name,
|
||||||
Title = model.Title,
|
Title = model.Title,
|
||||||
Address1 = model.Address, // Map to Address1
|
Address1 = model.Address,
|
||||||
City = model.City,
|
City = model.City,
|
||||||
State = model.State,
|
State = model.State,
|
||||||
Zip = model.ZipCode, // Map to Zip
|
Zip = model.ZipCode,
|
||||||
PhoneNumber = model.Phone, // Map to PhoneNumber
|
PhoneNumber = model.Phone,
|
||||||
Email = model.ContactEmail, // Map to Email
|
Email = model.ContactEmail,
|
||||||
Status = model.Status,
|
Status = model.Status,
|
||||||
CreatedDate = DateTime.Now
|
CreatedDate = DateTime.Now
|
||||||
// Contact and AccountId don't exist in database
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_db.Locations.Add(location);
|
await _locationDataService.AddAsync(location);
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
return Ok(new DataResponse { Message = "Location Created Successfully", Status = "200" });
|
return Ok(new DataResponse { Message = "Location Created Successfully", Status = "200" });
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -136,23 +119,22 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var exist = await _db.Locations.Where(l => l.Id == id).FirstOrDefaultAsync();
|
var exist = await _locationDataService.GetByIdAsync(id);
|
||||||
if (exist == null)
|
if (exist == null)
|
||||||
return BadRequest(new Response { Status = "Error", Message = "Location not found" });
|
return BadRequest(new Response { Status = "Error", Message = "Location not found" });
|
||||||
|
|
||||||
exist.Name = model.Name;
|
exist.Name = model.Name;
|
||||||
exist.Title = model.Title;
|
exist.Title = model.Title;
|
||||||
exist.Address1 = model.Address; // Map to Address1
|
exist.Address1 = model.Address;
|
||||||
exist.City = model.City;
|
exist.City = model.City;
|
||||||
exist.State = model.State;
|
exist.State = model.State;
|
||||||
exist.Zip = model.ZipCode; // Map to Zip
|
exist.Zip = model.ZipCode; // This is a property, not a method
|
||||||
exist.PhoneNumber = model.Phone; // Map to PhoneNumber
|
exist.PhoneNumber = model.Phone;
|
||||||
exist.Email = model.ContactEmail; // Map to Email
|
exist.Email = model.ContactEmail;
|
||||||
exist.Status = model.Status;
|
exist.Status = model.Status;
|
||||||
exist.LastModificationTime = DateTime.Now;
|
exist.LastModificationTime = DateTime.Now;
|
||||||
// Contact and AccountId don't exist in database
|
|
||||||
|
|
||||||
await _db.SaveChangesAsync();
|
await _locationDataService.UpdateAsync(exist);
|
||||||
return Ok(new DataResponse { Message = "Location Updated Successfully", Status = "200" });
|
return Ok(new DataResponse { Message = "Location Updated Successfully", Status = "200" });
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -166,12 +148,11 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var exist = await _db.Locations.Where(l => l.Id == id).FirstOrDefaultAsync();
|
var exist = await _locationDataService.GetByIdAsync(id);
|
||||||
if (exist == null)
|
if (exist == null)
|
||||||
return BadRequest(new Response { Status = "Error", Message = "Location not found" });
|
return BadRequest(new Response { Status = "Error", Message = "Location not found" });
|
||||||
|
|
||||||
_db.Locations.Remove(exist);
|
await _locationDataService.DeleteAsync(id);
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
return Ok(new DataResponse { Message = "Location Deleted Successfully", Status = "200" });
|
return Ok(new DataResponse { Message = "Location Deleted Successfully", Status = "200" });
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
||||||
|
|
@ -2,37 +2,36 @@
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/PMSchedule")]
|
[Route("api/PMSchedule")]
|
||||||
[Route("api/pmschedules")]
|
[Route("api/pmschedules")]
|
||||||
public class PMScheduleController : ControllerBase
|
public class PMScheduleController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ApplicationDbContext _db;
|
private readonly IPMScheduleService _pmScheduleService;
|
||||||
|
|
||||||
public PMScheduleController(ApplicationDbContext db)
|
public PMScheduleController(IPMScheduleService pmScheduleService)
|
||||||
{
|
{
|
||||||
_db = db;
|
_pmScheduleService = pmScheduleService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("GetList")]
|
[HttpGet("GetList")]
|
||||||
public IActionResult GetList()
|
public async Task<IActionResult> GetList()
|
||||||
{
|
{
|
||||||
var data = _db.PMSchedules
|
var items = await _pmScheduleService.GetAllPMSchedulesAsync();
|
||||||
.Include(x => x.Asset)
|
|
||||||
.Include(x => x.Location)
|
var data = items.Select(x => new
|
||||||
.OrderByDescending(x => x.Id)
|
{
|
||||||
.Select(x => new
|
Id = x.Id,
|
||||||
{
|
Name = x.Name,
|
||||||
x.Id,
|
Frequency = x.Frequency,
|
||||||
x.Name,
|
StartDate = x.StartDate,
|
||||||
x.Frequency,
|
IsActive = x.IsActive,
|
||||||
x.StartDate,
|
Asset = x.AssetName,
|
||||||
x.IsActive,
|
Location = x.LocationName
|
||||||
Asset = x.Asset != null ? x.Asset.Name : null,
|
});
|
||||||
Location = x.Location != null ? x.Location.Name : null
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
return Ok(data);
|
return Ok(data);
|
||||||
}
|
}
|
||||||
|
|
@ -40,31 +39,42 @@ public class PMScheduleController : ControllerBase
|
||||||
[HttpPost("Save")]
|
[HttpPost("Save")]
|
||||||
public async Task<IActionResult> Save(PMSchedule_DTO dto)
|
public async Task<IActionResult> Save(PMSchedule_DTO dto)
|
||||||
{
|
{
|
||||||
PMSchedules model;
|
try
|
||||||
|
|
||||||
if (dto.Id == 0)
|
|
||||||
{
|
{
|
||||||
model = new PMSchedules
|
var userId = User.Identity?.Name ?? "system";
|
||||||
|
|
||||||
|
if (dto.Id == 0)
|
||||||
{
|
{
|
||||||
CreatedDate = DateTime.UtcNow
|
var createDto = new CreatePMScheduleDTO
|
||||||
};
|
{
|
||||||
_db.PMSchedules.Add(model);
|
Name = dto.Name,
|
||||||
|
Frequency = dto.Frequency,
|
||||||
|
StartDate = dto.StartDate,
|
||||||
|
IsActive = dto.IsActive,
|
||||||
|
AssetId = dto.AssetId,
|
||||||
|
LocationId = dto.LocationId
|
||||||
|
};
|
||||||
|
await _pmScheduleService.CreatePMScheduleAsync(createDto, userId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var updateDto = new UpdatePMScheduleDTO
|
||||||
|
{
|
||||||
|
Name = dto.Name,
|
||||||
|
Frequency = dto.Frequency,
|
||||||
|
StartDate = dto.StartDate,
|
||||||
|
IsActive = dto.IsActive,
|
||||||
|
AssetId = dto.AssetId,
|
||||||
|
LocationId = dto.LocationId
|
||||||
|
};
|
||||||
|
await _pmScheduleService.UpdatePMScheduleAsync(dto.Id, updateDto, userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
}
|
}
|
||||||
else
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
model = await _db.PMSchedules.FindAsync(dto.Id);
|
return BadRequest(new { Message = ex.Message });
|
||||||
if (model == null) return NotFound();
|
|
||||||
model.LastModificationTime = DateTime.UtcNow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model.Name = dto.Name;
|
|
||||||
model.Frequency = dto.Frequency;
|
|
||||||
model.StartDate = dto.StartDate;
|
|
||||||
model.IsActive = dto.IsActive;
|
|
||||||
model.AssetId = dto.AssetId;
|
|
||||||
model.LocationId = dto.LocationId;
|
|
||||||
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
return Ok();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ using Data.SeaHavenIndustries;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
|
||||||
namespace Api.SeaHavenIndustries.Controllers
|
namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
|
|
@ -12,13 +14,15 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
[Route("api/vendors")]
|
[Route("api/vendors")]
|
||||||
public class VendorController : Controller
|
public class VendorController : Controller
|
||||||
{
|
{
|
||||||
private readonly ApplicationDbContext _db;
|
private readonly IVendorService _vendorService;
|
||||||
|
private readonly ApplicationDbContext _db; // Keep for complex queries like nearby vendors
|
||||||
private readonly Helper.ZipCodeDistance _zipDistance;
|
private readonly Helper.ZipCodeDistance _zipDistance;
|
||||||
private readonly Helper.VendorPortalTokenService _vendorTokens;
|
private readonly Helper.VendorPortalTokenService _vendorTokens;
|
||||||
private readonly IConfiguration _config;
|
private readonly IConfiguration _config;
|
||||||
|
|
||||||
public VendorController(ApplicationDbContext db, Helper.ZipCodeDistance zipDistance, Helper.VendorPortalTokenService vendorTokens, IConfiguration config)
|
public VendorController(IVendorService vendorService, ApplicationDbContext db, Helper.ZipCodeDistance zipDistance, Helper.VendorPortalTokenService vendorTokens, IConfiguration config)
|
||||||
{
|
{
|
||||||
|
_vendorService = vendorService;
|
||||||
_db = db;
|
_db = db;
|
||||||
_zipDistance = zipDistance;
|
_zipDistance = zipDistance;
|
||||||
_vendorTokens = vendorTokens;
|
_vendorTokens = vendorTokens;
|
||||||
|
|
@ -26,64 +30,32 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("GetVendorList")]
|
[HttpGet("GetVendorList")]
|
||||||
public IActionResult GetVendorList(string? search = "", int page = 1, int pageSize = 10)
|
public async Task<IActionResult> GetVendorList(string? search = "", int page = 1, int pageSize = 10)
|
||||||
{
|
{
|
||||||
var query = _db.Vendors.Where(v => v.IsActive);
|
var pagedResult = await _vendorService.GetVendorsPagedAsync(page, pageSize, search);
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(search))
|
var data = pagedResult.Items.Select(v => new
|
||||||
{
|
{
|
||||||
var s = search.ToLower();
|
v.Id,
|
||||||
query = query.Where(v =>
|
CompanyName = v.Name,
|
||||||
(v.CompanyName ?? "").ToLower().Contains(s) ||
|
v.Email,
|
||||||
(v.ContactName ?? "").ToLower().Contains(s) ||
|
v.Phone
|
||||||
(v.Email ?? "").ToLower().Contains(s) ||
|
});
|
||||||
(v.TradeSpecialties ?? "").ToLower().Contains(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
var totalCount = query.Count();
|
|
||||||
|
|
||||||
var data = query.OrderByDescending(v => v.Id)
|
|
||||||
.Skip((page - 1) * pageSize)
|
|
||||||
.Take(pageSize)
|
|
||||||
.Select(v => new
|
|
||||||
{
|
|
||||||
v.Id,
|
|
||||||
v.CompanyName,
|
|
||||||
v.ContactName,
|
|
||||||
v.Email,
|
|
||||||
v.Phone,
|
|
||||||
v.TradeSpecialties,
|
|
||||||
v.IsActive
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
return Ok(new Pagination_DTO
|
return Ok(new Pagination_DTO
|
||||||
{
|
{
|
||||||
Data = data,
|
Data = data,
|
||||||
PageNumber = page,
|
PageNumber = page,
|
||||||
PageSize = pageSize,
|
PageSize = pageSize,
|
||||||
TotalCount = totalCount,
|
TotalCount = pagedResult.TotalCount,
|
||||||
TotalPages = (int)Math.Ceiling(totalCount / (double)pageSize)
|
TotalPages = (int)Math.Ceiling(pagedResult.TotalCount / (double)pageSize)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public async Task<IActionResult> GetVendorById(int id)
|
public async Task<IActionResult> GetVendorById(int id)
|
||||||
{
|
{
|
||||||
var vendor = await _db.Vendors.Where(v => v.Id == id).Select(v => new
|
var vendor = await _vendorService.GetVendorByIdAsync(id);
|
||||||
{
|
|
||||||
v.Id,
|
|
||||||
v.CompanyName,
|
|
||||||
v.ContactName,
|
|
||||||
v.Email,
|
|
||||||
v.Phone,
|
|
||||||
v.Address,
|
|
||||||
v.City,
|
|
||||||
v.State,
|
|
||||||
v.Zip,
|
|
||||||
v.TradeSpecialties,
|
|
||||||
v.IsActive
|
|
||||||
}).FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
if (vendor == null)
|
if (vendor == null)
|
||||||
return NotFound(new Response { Status = "Error", Message = "Vendor not found" });
|
return NotFound(new Response { Status = "Error", Message = "Vendor not found" });
|
||||||
|
|
@ -96,21 +68,13 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var vendor = new Vendor
|
var createDto = new CreateVendorDTO
|
||||||
{
|
{
|
||||||
CompanyName = model.CompanyName,
|
Name = model.CompanyName ?? throw new ArgumentException("CompanyName is required")
|
||||||
ContactName = model.ContactName,
|
|
||||||
Email = model.Email,
|
|
||||||
Phone = model.Phone,
|
|
||||||
Address = model.Address,
|
|
||||||
City = model.City,
|
|
||||||
State = model.State,
|
|
||||||
Zip = model.Zip,
|
|
||||||
TradeSpecialties = model.TradeSpecialties,
|
|
||||||
IsActive = model.IsActive
|
|
||||||
};
|
};
|
||||||
_db.Vendors.Add(vendor);
|
|
||||||
await _db.SaveChangesAsync();
|
var userId = User.Identity?.Name ?? "system";
|
||||||
|
await _vendorService.CreateVendorAsync(createDto, userId);
|
||||||
return Ok(new DataResponse { Message = "Vendor Created", Status = "200" });
|
return Ok(new DataResponse { Message = "Vendor Created", Status = "200" });
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -124,22 +88,13 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var exist = await _db.Vendors.FindAsync(id);
|
var updateDto = new UpdateVendorDTO
|
||||||
if (exist == null)
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = "Vendor not found" });
|
Name = model.CompanyName
|
||||||
|
};
|
||||||
|
|
||||||
exist.CompanyName = model.CompanyName;
|
var userId = User.Identity?.Name ?? "system";
|
||||||
exist.ContactName = model.ContactName;
|
await _vendorService.UpdateVendorAsync(id, updateDto, userId);
|
||||||
exist.Email = model.Email;
|
|
||||||
exist.Phone = model.Phone;
|
|
||||||
exist.Address = model.Address;
|
|
||||||
exist.City = model.City;
|
|
||||||
exist.State = model.State;
|
|
||||||
exist.Zip = model.Zip;
|
|
||||||
exist.TradeSpecialties = model.TradeSpecialties;
|
|
||||||
exist.IsActive = model.IsActive;
|
|
||||||
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
return Ok(new DataResponse { Message = "Vendor Updated", Status = "200" });
|
return Ok(new DataResponse { Message = "Vendor Updated", Status = "200" });
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -151,12 +106,8 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
[HttpDelete("{id}")]
|
[HttpDelete("{id}")]
|
||||||
public async Task<IActionResult> Delete(int id)
|
public async Task<IActionResult> Delete(int id)
|
||||||
{
|
{
|
||||||
var exist = await _db.Vendors.FindAsync(id);
|
var userId = User.Identity?.Name ?? "system";
|
||||||
if (exist == null)
|
await _vendorService.DeleteVendorAsync(id, userId);
|
||||||
return BadRequest(new Response { Status = "Error", Message = "Vendor not found" });
|
|
||||||
|
|
||||||
_db.Vendors.Remove(exist);
|
|
||||||
await _db.SaveChangesAsync();
|
|
||||||
return Ok(new DataResponse { Message = "Vendor Deleted", Status = "200" });
|
return Ok(new DataResponse { Message = "Vendor Deleted", Status = "200" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ using System.IO;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
|
using SeaHaven.DataServices.Interfaces;
|
||||||
|
|
||||||
namespace Api.SeaHavenIndustries.Controllers
|
namespace Api.SeaHavenIndustries.Controllers
|
||||||
{
|
{
|
||||||
|
|
@ -23,15 +24,26 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
public class WorkOrderController : Controller
|
public class WorkOrderController : Controller
|
||||||
{
|
{
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
private readonly ApplicationDbContext _db;
|
private readonly IWorkOrderDataService _workOrderDataService;
|
||||||
|
private readonly ApplicationDbContext _db; // Keep for complex operations, file handling, dispatch, comments
|
||||||
private readonly IWebHostEnvironment _webHostEnvironment;
|
private readonly IWebHostEnvironment _webHostEnvironment;
|
||||||
IHttpContextAccessor _httpContext;
|
IHttpContextAccessor _httpContext;
|
||||||
private readonly Helper.SendMessage _sendMessage;
|
private readonly Helper.SendMessage _sendMessage;
|
||||||
private readonly Helper.VendorPortalTokenService _vendorTokens;
|
private readonly Helper.VendorPortalTokenService _vendorTokens;
|
||||||
private readonly IConfiguration _config;
|
private readonly IConfiguration _config;
|
||||||
public WorkOrderController(UserManager<ApplicationUser> userManager, ApplicationDbContext db, IWebHostEnvironment webHostEnvironment, IHttpContextAccessor httpContext, Helper.SendMessage sendMessage, Helper.VendorPortalTokenService vendorTokens, IConfiguration config)
|
|
||||||
|
public WorkOrderController(
|
||||||
|
UserManager<ApplicationUser> userManager,
|
||||||
|
IWorkOrderDataService workOrderDataService,
|
||||||
|
ApplicationDbContext db,
|
||||||
|
IWebHostEnvironment webHostEnvironment,
|
||||||
|
IHttpContextAccessor httpContext,
|
||||||
|
Helper.SendMessage sendMessage,
|
||||||
|
Helper.VendorPortalTokenService vendorTokens,
|
||||||
|
IConfiguration config)
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
|
_workOrderDataService = workOrderDataService;
|
||||||
_db = db;
|
_db = db;
|
||||||
_webHostEnvironment = webHostEnvironment;
|
_webHostEnvironment = webHostEnvironment;
|
||||||
_httpContext = httpContext;
|
_httpContext = httpContext;
|
||||||
|
|
@ -373,79 +385,17 @@ namespace Api.SeaHavenIndustries.Controllers
|
||||||
// GET: api/WorkOrder/GetWorkOrderList
|
// GET: api/WorkOrder/GetWorkOrderList
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
[HttpGet("GetWorkOrderList")]
|
[HttpGet("GetWorkOrderList")]
|
||||||
public IActionResult GetWorkOrderList(string? search = "", int page = 1, int pageSize = 12, string? sortBy = "lastUpdated", string? sortDir = "desc", string? status = "", string? assignee = "", int? locationId = null)
|
public async Task<IActionResult> GetWorkOrderList(string? search = "", int page = 1, int pageSize = 12, string? sortBy = "lastUpdated", string? sortDir = "desc", string? status = "", string? assignee = "", int? locationId = null)
|
||||||
{
|
{
|
||||||
search ??= "";
|
var (data, totalCount) = await _workOrderDataService.GetWorkOrderListPagedAsync(
|
||||||
|
page,
|
||||||
var query = _db.workOrders
|
pageSize,
|
||||||
.Include(w => w.Locations)
|
search,
|
||||||
.Include(w => w.AssignToUser)
|
status,
|
||||||
.Where(w => w.istemplate != true);
|
assignee,
|
||||||
|
locationId,
|
||||||
if (locationId.HasValue)
|
sortBy,
|
||||||
query = query.Where(w => w.LocationId == locationId.Value);
|
sortDir);
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(status))
|
|
||||||
query = query.Where(w => w.Status == status);
|
|
||||||
|
|
||||||
if (assignee == "__unassigned")
|
|
||||||
query = query.Where(w => w.AssignTo == null || w.AssignTo == "");
|
|
||||||
else if (!string.IsNullOrWhiteSpace(assignee))
|
|
||||||
query = query.Where(w => w.AssignToUser != null && (w.AssignToUser.FirstName + " " + w.AssignToUser.LastName).Contains(assignee));
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(search))
|
|
||||||
{
|
|
||||||
var s = search.ToLower();
|
|
||||||
query = query.Where(w =>
|
|
||||||
(w.InternalWONumber ?? "").ToLower().Contains(s) ||
|
|
||||||
(w.WorkerOrderNumber ?? "").ToLower().Contains(s) ||
|
|
||||||
(w.WorkerOrderTitle ?? "").ToLower().Contains(s) ||
|
|
||||||
(w.Locations.Title ?? "").ToLower().Contains(s) ||
|
|
||||||
(w.Locations.Name ?? "").ToLower().Contains(s)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
var totalCount = query.Count();
|
|
||||||
|
|
||||||
var isAsc = sortDir?.ToLower() == "asc";
|
|
||||||
IOrderedQueryable<WorkOrder> ordered = (sortBy?.ToLower()) switch
|
|
||||||
{
|
|
||||||
"number" => isAsc ? query.OrderBy(w => w.InternalWONumber) : query.OrderByDescending(w => w.InternalWONumber),
|
|
||||||
"title" => isAsc ? query.OrderBy(w => w.WorkerOrderTitle) : query.OrderByDescending(w => w.WorkerOrderTitle),
|
|
||||||
"location" => isAsc ? query.OrderBy(w => w.Locations != null ? w.Locations.Name : "") : query.OrderByDescending(w => w.Locations != null ? w.Locations.Name : ""),
|
|
||||||
"priority" => isAsc ? query.OrderBy(w => w.Priority) : query.OrderByDescending(w => w.Priority),
|
|
||||||
"status" => isAsc ? query.OrderBy(w => w.Status) : query.OrderByDescending(w => w.Status),
|
|
||||||
"createddate" => isAsc ? query.OrderBy(w => w.CreatedDate) : query.OrderByDescending(w => w.CreatedDate),
|
|
||||||
"assignedto" => isAsc ? query.OrderBy(w => w.AssignToUser != null ? w.AssignToUser.FirstName : "") : query.OrderByDescending(w => w.AssignToUser != null ? w.AssignToUser.FirstName : ""),
|
|
||||||
"lastupdated" => isAsc ? query.OrderBy(w => w.LastModificationTime) : query.OrderByDescending(w => w.LastModificationTime),
|
|
||||||
_ => query.OrderByDescending(w => w.Id)
|
|
||||||
};
|
|
||||||
|
|
||||||
var data = ordered
|
|
||||||
.Skip((page - 1) * pageSize)
|
|
||||||
.Take(pageSize)
|
|
||||||
.Select(w => new
|
|
||||||
{
|
|
||||||
id = w.Id,
|
|
||||||
internalWONumber = w.InternalWONumber,
|
|
||||||
workOrderNumber = w.WorkerOrderNumber,
|
|
||||||
number = w.InternalWONumber ?? w.WorkerOrderNumber,
|
|
||||||
title = w.WorkerOrderTitle,
|
|
||||||
location = w.Locations != null ? w.Locations.Name : "",
|
|
||||||
locationName = w.Locations != null ? w.Locations.Name : "",
|
|
||||||
priority = w.Priority,
|
|
||||||
status = w.Status,
|
|
||||||
createdDate = w.CreatedDate,
|
|
||||||
dueDate = w.DueDate,
|
|
||||||
assignedTo = w.AssignToUser != null ? w.AssignToUser.FirstName + " " + w.AssignToUser.LastName : "",
|
|
||||||
employeeName = w.AssignToUser != null ? w.AssignToUser.FirstName + " " + w.AssignToUser.LastName : "",
|
|
||||||
lastUpdated = new[] {
|
|
||||||
w.LastModificationTime,
|
|
||||||
w.Comments.Max(c => (DateTime?)c.CreatedDate),
|
|
||||||
_db.WorkOrderAuditLogs.Where(a => a.WorkOrderId == w.Id).Max(a => (DateTime?)a.CreatedAt)
|
|
||||||
}.Where(d => d.HasValue).Max()
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var viewModel = new Pagination_DTO
|
var viewModel = new Pagination_DTO
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
namespace Api.SeaHavenIndustries.DTOs
|
using Data.SeaHavenIndustries;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
|
||||||
|
namespace Api.SeaHavenIndustries.DTOs
|
||||||
{
|
{
|
||||||
public class Contact_DTO
|
public class Contact_DTO
|
||||||
{
|
{
|
||||||
|
|
@ -20,5 +23,100 @@
|
||||||
public string? TwitterUrl { get; set; }
|
public string? TwitterUrl { get; set; }
|
||||||
public int? LocationId { get; set; }
|
public int? LocationId { get; set; }
|
||||||
public int? AccountId { get; set; }
|
public int? AccountId { get; set; }
|
||||||
|
|
||||||
|
// ✅ Map API DTO to Service DTO
|
||||||
|
public CreateContactDTO ToServiceCreateDTO()
|
||||||
|
{
|
||||||
|
return new CreateContactDTO
|
||||||
|
{
|
||||||
|
FirstName = this.FirstName,
|
||||||
|
LastName = this.LastName,
|
||||||
|
Email = this.Email ?? "",
|
||||||
|
Phone = this.PhoneNumber,
|
||||||
|
Title = this.Title,
|
||||||
|
Type = this.ContactType,
|
||||||
|
AccountId = this.AccountId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map from Entity to DTO (Model)
|
||||||
|
public static Contact_DTO MapToModel(Contacts entity)
|
||||||
|
{
|
||||||
|
return new Contact_DTO
|
||||||
|
{
|
||||||
|
Title = entity.Title,
|
||||||
|
Owner = entity.Owner,
|
||||||
|
FirstName = entity.FirstName,
|
||||||
|
MiddleName = entity.MiddleName,
|
||||||
|
LastName = entity.LastName,
|
||||||
|
ContactType = entity.ContactType,
|
||||||
|
PhoneNumber = entity.PhoneNumber,
|
||||||
|
Email = entity.Email,
|
||||||
|
Address1 = entity.Address1,
|
||||||
|
Address2 = entity.Address2,
|
||||||
|
City = entity.City,
|
||||||
|
State = entity.State,
|
||||||
|
Zip = entity.Zip,
|
||||||
|
FacebookUrl = entity.FacebookUrl,
|
||||||
|
LinkedInUrl = entity.LinkedInUrl,
|
||||||
|
TwitterUrl = entity.TwitterUrl,
|
||||||
|
LocationId = entity.LocationId,
|
||||||
|
AccountId = entity.AccountId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map from DTO (Model) to Entity
|
||||||
|
public static Contacts MapToEntity(Contact_DTO dto, Contacts? existingEntity = null)
|
||||||
|
{
|
||||||
|
var entity = existingEntity ?? new Contacts();
|
||||||
|
|
||||||
|
entity.Title = dto.Title;
|
||||||
|
entity.Owner = dto.Owner;
|
||||||
|
entity.FirstName = dto.FirstName;
|
||||||
|
entity.MiddleName = dto.MiddleName;
|
||||||
|
entity.LastName = dto.LastName;
|
||||||
|
entity.ContactType = dto.ContactType;
|
||||||
|
entity.PhoneNumber = dto.PhoneNumber;
|
||||||
|
entity.Email = dto.Email;
|
||||||
|
entity.Address1 = dto.Address1;
|
||||||
|
entity.Address2 = dto.Address2;
|
||||||
|
entity.City = dto.City;
|
||||||
|
entity.State = dto.State;
|
||||||
|
entity.Zip = dto.Zip;
|
||||||
|
entity.FacebookUrl = dto.FacebookUrl;
|
||||||
|
entity.LinkedInUrl = dto.LinkedInUrl;
|
||||||
|
entity.TwitterUrl = dto.TwitterUrl;
|
||||||
|
entity.LocationId = dto.LocationId;
|
||||||
|
entity.AccountId = dto.AccountId;
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DTO for contact list view
|
||||||
|
public class ContactListItem_DTO
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? Email { get; set; }
|
||||||
|
public string? Phone { get; set; }
|
||||||
|
|
||||||
|
// ✅ Map from Service DTO
|
||||||
|
public static ContactListItem_DTO FromServiceDTO(ContactDTO serviceDto)
|
||||||
|
{
|
||||||
|
return new ContactListItem_DTO
|
||||||
|
{
|
||||||
|
Id = serviceDto.Id,
|
||||||
|
Name = (serviceDto.FirstName + " " + serviceDto.LastName).Trim(),
|
||||||
|
Email = serviceDto.Email,
|
||||||
|
Phone = serviceDto.Phone
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Map collection from Service DTOs
|
||||||
|
public static IEnumerable<ContactListItem_DTO> FromServiceDTOs(IEnumerable<ContactDTO> serviceDtos)
|
||||||
|
{
|
||||||
|
return serviceDtos.Select(FromServiceDTO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
namespace Api.SeaHavenIndustries.DTOs
|
using Data.SeaHavenIndustries;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
|
||||||
|
namespace Api.SeaHavenIndustries.DTOs
|
||||||
{
|
{
|
||||||
public class EditContact_DTO
|
public class EditContact_DTO
|
||||||
{
|
{
|
||||||
|
|
@ -21,5 +24,72 @@
|
||||||
public string? TwitterUrl { get; set; }
|
public string? TwitterUrl { get; set; }
|
||||||
public int? LocationId { get; set; }
|
public int? LocationId { get; set; }
|
||||||
public int? AccountId { get; set; }
|
public int? AccountId { get; set; }
|
||||||
|
|
||||||
|
// ✅ Map API DTO to Service DTO
|
||||||
|
public UpdateContactDTO ToServiceUpdateDTO()
|
||||||
|
{
|
||||||
|
return new UpdateContactDTO
|
||||||
|
{
|
||||||
|
FirstName = this.FirstName,
|
||||||
|
LastName = this.LastName,
|
||||||
|
Email = this.Email,
|
||||||
|
Phone = this.PhoneNumber,
|
||||||
|
Title = this.Title,
|
||||||
|
Type = this.ContactType,
|
||||||
|
AccountId = this.AccountId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map from Entity to DTO (Model)
|
||||||
|
public static EditContact_DTO MapToModel(Contacts entity)
|
||||||
|
{
|
||||||
|
return new EditContact_DTO
|
||||||
|
{
|
||||||
|
Id = entity.Id,
|
||||||
|
Title = entity.Title,
|
||||||
|
Owner = entity.Owner,
|
||||||
|
FirstName = entity.FirstName,
|
||||||
|
MiddleName = entity.MiddleName,
|
||||||
|
LastName = entity.LastName,
|
||||||
|
ContactType = entity.ContactType,
|
||||||
|
PhoneNumber = entity.PhoneNumber,
|
||||||
|
Email = entity.Email,
|
||||||
|
Address1 = entity.Address1,
|
||||||
|
Address2 = entity.Address2,
|
||||||
|
City = entity.City,
|
||||||
|
State = entity.State,
|
||||||
|
Zip = entity.Zip,
|
||||||
|
FacebookUrl = entity.FacebookUrl,
|
||||||
|
LinkedInUrl = entity.LinkedInUrl,
|
||||||
|
TwitterUrl = entity.TwitterUrl,
|
||||||
|
LocationId = entity.LocationId,
|
||||||
|
AccountId = entity.AccountId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map from DTO (Model) to Entity - updates existing entity
|
||||||
|
public static Contacts MapToEntity(EditContact_DTO dto, Contacts existingEntity)
|
||||||
|
{
|
||||||
|
existingEntity.Title = dto.Title;
|
||||||
|
existingEntity.Owner = dto.Owner;
|
||||||
|
existingEntity.FirstName = dto.FirstName;
|
||||||
|
existingEntity.MiddleName = dto.MiddleName;
|
||||||
|
existingEntity.LastName = dto.LastName;
|
||||||
|
existingEntity.ContactType = dto.ContactType;
|
||||||
|
existingEntity.PhoneNumber = dto.PhoneNumber;
|
||||||
|
existingEntity.Email = dto.Email;
|
||||||
|
existingEntity.Address1 = dto.Address1;
|
||||||
|
existingEntity.Address2 = dto.Address2;
|
||||||
|
existingEntity.City = dto.City;
|
||||||
|
existingEntity.State = dto.State;
|
||||||
|
existingEntity.Zip = dto.Zip;
|
||||||
|
existingEntity.FacebookUrl = dto.FacebookUrl;
|
||||||
|
existingEntity.LinkedInUrl = dto.LinkedInUrl;
|
||||||
|
existingEntity.TwitterUrl = dto.TwitterUrl;
|
||||||
|
existingEntity.LocationId = dto.LocationId;
|
||||||
|
existingEntity.AccountId = dto.AccountId;
|
||||||
|
|
||||||
|
return existingEntity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
|
||||||
namespace Api.SeaHavenIndustries.DTOs
|
namespace Api.SeaHavenIndustries.DTOs
|
||||||
{
|
{
|
||||||
public class EditLocation_DTO
|
public class EditLocation_DTO
|
||||||
|
|
@ -17,5 +19,19 @@ namespace Api.SeaHavenIndustries.DTOs
|
||||||
|
|
||||||
public int? GetAccountId() =>
|
public int? GetAccountId() =>
|
||||||
int.TryParse(AccountId, out var id) ? id : null;
|
int.TryParse(AccountId, out var id) ? id : null;
|
||||||
|
|
||||||
|
// ✅ Map API DTO to Service DTO
|
||||||
|
public UpdateLocationDTO ToServiceUpdateDTO()
|
||||||
|
{
|
||||||
|
return new UpdateLocationDTO
|
||||||
|
{
|
||||||
|
LocationName = this.Name,
|
||||||
|
Address = this.Address,
|
||||||
|
City = this.City,
|
||||||
|
State = this.State,
|
||||||
|
Zipcode = this.ZipCode,
|
||||||
|
AccountId = this.GetAccountId()
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
using Data.SeaHavenIndustries;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
|
||||||
namespace Api.SeaHavenIndustries.DTOs
|
namespace Api.SeaHavenIndustries.DTOs
|
||||||
{
|
{
|
||||||
public class Location_DTO
|
public class Location_DTO
|
||||||
|
|
@ -16,5 +19,117 @@ namespace Api.SeaHavenIndustries.DTOs
|
||||||
|
|
||||||
public int? GetAccountId() =>
|
public int? GetAccountId() =>
|
||||||
int.TryParse(AccountId, out var id) ? id : null;
|
int.TryParse(AccountId, out var id) ? id : null;
|
||||||
|
|
||||||
|
// ✅ Map API DTO to Service DTO
|
||||||
|
public CreateLocationDTO ToServiceCreateDTO()
|
||||||
|
{
|
||||||
|
return new CreateLocationDTO
|
||||||
|
{
|
||||||
|
LocationName = this.Name ?? "",
|
||||||
|
Address = this.Address,
|
||||||
|
City = this.City,
|
||||||
|
State = this.State,
|
||||||
|
Zipcode = this.ZipCode,
|
||||||
|
AccountId = this.GetAccountId()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map from Entity to DTO
|
||||||
|
public static Location_DTO MapToModel(Locations entity)
|
||||||
|
{
|
||||||
|
return new Location_DTO
|
||||||
|
{
|
||||||
|
Title = entity.Title,
|
||||||
|
Name = entity.Name,
|
||||||
|
Address = entity.Address1,
|
||||||
|
City = entity.City,
|
||||||
|
State = entity.State,
|
||||||
|
ZipCode = entity.Zip,
|
||||||
|
Phone = entity.PhoneNumber,
|
||||||
|
Contact = null, // Not in database schema
|
||||||
|
ContactEmail = entity.Email,
|
||||||
|
Status = entity.Status,
|
||||||
|
AccountId = null // Not in database schema
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map from DTO to Entity
|
||||||
|
public static Locations MapToEntity(Location_DTO dto, Locations? existingEntity = null)
|
||||||
|
{
|
||||||
|
var entity = existingEntity ?? new Locations();
|
||||||
|
|
||||||
|
entity.Title = dto.Title;
|
||||||
|
entity.Name = dto.Name;
|
||||||
|
entity.Address1 = dto.Address;
|
||||||
|
entity.City = dto.City;
|
||||||
|
entity.State = dto.State;
|
||||||
|
entity.Zip = dto.ZipCode;
|
||||||
|
entity.PhoneNumber = dto.Phone;
|
||||||
|
// Contact field doesn't exist in database schema - ignored
|
||||||
|
entity.Email = dto.ContactEmail;
|
||||||
|
entity.Status = dto.Status;
|
||||||
|
// AccountId field doesn't exist in database schema - ignored
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DTO for list views
|
||||||
|
public class LocationListItem_DTO
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? Title { get; set; }
|
||||||
|
|
||||||
|
// Map from Entity
|
||||||
|
public static LocationListItem_DTO MapToModel(Locations entity)
|
||||||
|
{
|
||||||
|
return new LocationListItem_DTO
|
||||||
|
{
|
||||||
|
Id = entity.Id,
|
||||||
|
Name = entity.Name,
|
||||||
|
Title = entity.Title
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Map from Service DTO (no logic in controller)
|
||||||
|
public static LocationListItem_DTO FromServiceDTO(LocationDTO serviceDto)
|
||||||
|
{
|
||||||
|
return new LocationListItem_DTO
|
||||||
|
{
|
||||||
|
Id = serviceDto.Id,
|
||||||
|
Name = serviceDto.Name ?? serviceDto.Title,
|
||||||
|
Title = serviceDto.Title ?? serviceDto.Name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Map collection from Service DTOs
|
||||||
|
public static IEnumerable<LocationListItem_DTO> FromServiceDTOs(IEnumerable<LocationDTO> serviceDtos)
|
||||||
|
{
|
||||||
|
return serviceDtos.Select(FromServiceDTO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DTO for location dropdown/simple view
|
||||||
|
public class LocationViewModel_DTO
|
||||||
|
{
|
||||||
|
public int? Id { get; set; }
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
// ✅ Map from Service DTO
|
||||||
|
public static LocationViewModel_DTO FromServiceDTO(LocationDTO serviceDto)
|
||||||
|
{
|
||||||
|
return new LocationViewModel_DTO
|
||||||
|
{
|
||||||
|
Id = serviceDto.Id,
|
||||||
|
Name = serviceDto.Name ?? serviceDto.Title
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Map collection from Service DTOs
|
||||||
|
public static IEnumerable<LocationViewModel_DTO> FromServiceDTOs(IEnumerable<LocationDTO> serviceDtos)
|
||||||
|
{
|
||||||
|
return serviceDtos.Select(FromServiceDTO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,12 +60,17 @@ builder.Services.AddScoped<SeaHaven.DataServices.Interfaces.IPMScheduleDataServi
|
||||||
builder.Services.AddScoped<SeaHaven.DataServices.Interfaces.IAssetDataService, SeaHaven.DataServices.Implementation.AssetDataService>();
|
builder.Services.AddScoped<SeaHaven.DataServices.Interfaces.IAssetDataService, SeaHaven.DataServices.Implementation.AssetDataService>();
|
||||||
builder.Services.AddScoped<SeaHaven.DataServices.Interfaces.ICategoryDataService, SeaHaven.DataServices.Implementation.CategoryDataService>();
|
builder.Services.AddScoped<SeaHaven.DataServices.Interfaces.ICategoryDataService, SeaHaven.DataServices.Implementation.CategoryDataService>();
|
||||||
|
|
||||||
// Business Services (Business Logic Layer) - Only register services that exist
|
// Business Services (Business Logic Layer)
|
||||||
builder.Services.AddScoped<SeaHaven.Services.Interfaces.IContactService, SeaHaven.Services.Implementation.ContactService>();
|
builder.Services.AddScoped<SeaHaven.Services.Interfaces.IContactService, SeaHaven.Services.Implementation.ContactService>();
|
||||||
builder.Services.AddScoped<SeaHaven.Services.Interfaces.IWorkOrderService, SeaHaven.Services.Implementation.WorkOrderService>();
|
builder.Services.AddScoped<SeaHaven.Services.Interfaces.IWorkOrderService, SeaHaven.Services.Implementation.WorkOrderService>();
|
||||||
// TODO: Add other business services as they are implemented
|
builder.Services.AddScoped<SeaHaven.Services.Interfaces.ILocationService, SeaHaven.Services.Implementation.LocationService>();
|
||||||
// - LocationService, EmployeeService, AccountService, VendorService, DispatchService
|
builder.Services.AddScoped<SeaHaven.Services.Interfaces.IEmployeeService, SeaHaven.Services.Implementation.EmployeeService>();
|
||||||
// - FollowUpService, PMScheduleService, AssetService, CategoryService
|
builder.Services.AddScoped<SeaHaven.Services.Interfaces.IAccountService, SeaHaven.Services.Implementation.AccountService>();
|
||||||
|
builder.Services.AddScoped<SeaHaven.Services.Interfaces.IVendorService, SeaHaven.Services.Implementation.VendorService>();
|
||||||
|
builder.Services.AddScoped<SeaHaven.Services.Interfaces.IDispatchService, SeaHaven.Services.Implementation.DispatchService>();
|
||||||
|
builder.Services.AddScoped<SeaHaven.Services.Interfaces.IFollowUpService, SeaHaven.Services.Implementation.FollowUpService>();
|
||||||
|
builder.Services.AddScoped<SeaHaven.Services.Interfaces.IPMScheduleService, SeaHaven.Services.Implementation.PMScheduleService>();
|
||||||
|
builder.Services.AddScoped<SeaHaven.Services.Interfaces.IAssetService, SeaHaven.Services.Implementation.AssetService>();
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,8 +86,9 @@ namespace Data.SeaHavenIndustries
|
||||||
public Employee Employee { get; set; } = null!;
|
public Employee Employee { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class EmployeeEmail : FullAuditEntity
|
public class EmployeeEmail
|
||||||
{
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
public int EmployeeId { get; set; }
|
public int EmployeeId { get; set; }
|
||||||
public Employee? Employee { get; set; }
|
public Employee? Employee { get; set; }
|
||||||
|
|
||||||
|
|
@ -99,22 +100,28 @@ namespace Data.SeaHavenIndustries
|
||||||
public bool? IsPrimary { get; set; }
|
public bool? IsPrimary { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Department : FullAuditEntity
|
public class Department
|
||||||
{
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
[MaxLength(200)]
|
[MaxLength(200)]
|
||||||
public string Name { get; set; } = null!;
|
public string Name { get; set; } = null!;
|
||||||
public ICollection<Employee>? Employees { get; set; }
|
public ICollection<Employee>? Employees { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class JobTitle : FullAuditEntity
|
public class JobTitle
|
||||||
{
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
[MaxLength(200)]
|
[MaxLength(200)]
|
||||||
public string Name { get; set; } = null!;
|
public string Name { get; set; } = null!;
|
||||||
public ICollection<Employee>? Employees { get; set; }
|
public ICollection<Employee>? Employees { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Region : FullAuditEntity
|
public class Region
|
||||||
{
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
[MaxLength(200)]
|
[MaxLength(200)]
|
||||||
public string Name { get; set; } = null!;
|
public string Name { get; set; } = null!;
|
||||||
public ICollection<Employee>? Employees { get; set; }
|
public ICollection<Employee>? Employees { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -32,20 +32,29 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(IEnumerable<Accounts> Items, int TotalCount)> GetPagedAsync(
|
public async Task<(IEnumerable<Accounts> Items, int TotalCount)> GetPagedAsync(
|
||||||
int page,
|
int page,
|
||||||
int pageSize,
|
int pageSize,
|
||||||
string? search = null)
|
string? search = null)
|
||||||
{
|
{
|
||||||
var query = _context.Accounts.AsQueryable();
|
search ??= "";
|
||||||
|
|
||||||
|
var query = _context.Accounts
|
||||||
|
.Where(a => a.IsDeleted == false || a.IsDeleted == null);
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(search))
|
if (!string.IsNullOrWhiteSpace(search))
|
||||||
{
|
{
|
||||||
query = query.Where(a => a.Name!.Contains(search));
|
var s = search.ToLower();
|
||||||
|
query = query.Where(a =>
|
||||||
|
(a.Name ?? "").ToLower().Contains(s) ||
|
||||||
|
(a.Email ?? "").ToLower().Contains(s) ||
|
||||||
|
(a.Phone ?? "").Contains(s) ||
|
||||||
|
(a.Website ?? "").ToLower().Contains(s)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalCount = await query.CountAsync();
|
var totalCount = await query.CountAsync();
|
||||||
var items = await query
|
var items = await query
|
||||||
.OrderBy(a => a.Name)
|
.OrderByDescending(a => a.Id)
|
||||||
.Skip((page - 1) * pageSize)
|
.Skip((page - 1) * pageSize)
|
||||||
.Take(pageSize)
|
.Take(pageSize)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
public async Task<Assets?> GetByIdWithDetailsAsync(int id)
|
public async Task<Assets?> GetByIdWithDetailsAsync(int id)
|
||||||
{
|
{
|
||||||
return await _context.Assets
|
return await _context.Assets
|
||||||
|
.Include(a => a.Account)
|
||||||
|
.Include(a => a.Location)
|
||||||
.FirstOrDefaultAsync(a => a.Id == id);
|
.FirstOrDefaultAsync(a => a.Id == id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -37,15 +39,30 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(IEnumerable<Assets> Items, int TotalCount)> GetPagedAsync(
|
public async Task<(IEnumerable<Assets> Items, int TotalCount)> GetPagedAsync(
|
||||||
int page,
|
int page,
|
||||||
int pageSize,
|
int pageSize,
|
||||||
string? search = null)
|
string? search = null)
|
||||||
{
|
{
|
||||||
var query = _context.Assets.AsQueryable();
|
search ??= "";
|
||||||
|
|
||||||
|
var query = _context.Assets
|
||||||
|
.Include(a => a.Account)
|
||||||
|
.Include(a => a.Location)
|
||||||
|
.AsQueryable();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(search))
|
||||||
|
{
|
||||||
|
var s = search.ToLower();
|
||||||
|
query = query.Where(a =>
|
||||||
|
(a.Name != null && a.Name.ToLower().Contains(s)) ||
|
||||||
|
(a.AssetCode != null && a.AssetCode.ToLower().Contains(s)) ||
|
||||||
|
(a.Description != null && a.Description.ToLower().Contains(s))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
var totalCount = await query.CountAsync();
|
var totalCount = await query.CountAsync();
|
||||||
var items = await query
|
var items = await query
|
||||||
.OrderBy(a => a.Id)
|
.OrderByDescending(a => a.Id)
|
||||||
.Skip((page - 1) * pageSize)
|
.Skip((page - 1) * pageSize)
|
||||||
.Take(pageSize)
|
.Take(pageSize)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
|
||||||
|
|
@ -65,18 +65,22 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(IEnumerable<Contacts> Items, int TotalCount)> GetPagedAsync(
|
public async Task<(IEnumerable<Contacts> Items, int TotalCount)> GetPagedAsync(
|
||||||
int page,
|
int page,
|
||||||
int pageSize,
|
int pageSize,
|
||||||
string? search = null,
|
string? search = null,
|
||||||
string? type = null)
|
string? type = null)
|
||||||
{
|
{
|
||||||
|
search ??= "";
|
||||||
var query = _context.Contacts.AsQueryable();
|
var query = _context.Contacts.AsQueryable();
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(search))
|
if (!string.IsNullOrWhiteSpace(search))
|
||||||
{
|
{
|
||||||
query = query.Where(c =>
|
var s = search.ToLower();
|
||||||
(c.FirstName + " " + c.LastName).Contains(search) ||
|
query = query.Where(c =>
|
||||||
c.Email!.Contains(search));
|
(c.FirstName != null && c.FirstName.ToLower().Contains(s)) ||
|
||||||
|
(c.LastName != null && c.LastName.ToLower().Contains(s)) ||
|
||||||
|
(c.Email != null && c.Email.ToLower().Contains(s)) ||
|
||||||
|
(c.PhoneNumber != null && c.PhoneNumber.Contains(s)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(type))
|
if (!string.IsNullOrWhiteSpace(type))
|
||||||
|
|
@ -86,7 +90,7 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
|
|
||||||
var totalCount = await query.CountAsync();
|
var totalCount = await query.CountAsync();
|
||||||
var items = await query
|
var items = await query
|
||||||
.OrderBy(c => c.LastName)
|
.OrderByDescending(c => c.Id)
|
||||||
.Skip((page - 1) * pageSize)
|
.Skip((page - 1) * pageSize)
|
||||||
.Take(pageSize)
|
.Take(pageSize)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
return await _context.Employees
|
return await _context.Employees
|
||||||
.Include(e => e.Department)
|
.Include(e => e.Department)
|
||||||
.Include(e => e.JobTitle)
|
.Include(e => e.JobTitle)
|
||||||
|
.Include(e => e.Region)
|
||||||
.Include(e => e.Emails)
|
.Include(e => e.Emails)
|
||||||
|
.Include(e => e.Phones)
|
||||||
.FirstOrDefaultAsync(e => e.Id == id);
|
.FirstOrDefaultAsync(e => e.Id == id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,20 +35,34 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(IEnumerable<Employee> Items, int TotalCount)> GetPagedAsync(
|
public async Task<(IEnumerable<Employee> Items, int TotalCount)> GetPagedAsync(
|
||||||
int page,
|
int page,
|
||||||
int pageSize,
|
int pageSize,
|
||||||
string? search = null)
|
string? search = null)
|
||||||
{
|
{
|
||||||
var query = _context.Employees.AsQueryable();
|
search ??= "";
|
||||||
|
|
||||||
|
var query = _context.Employees
|
||||||
|
.Include(e => e.JobTitle)
|
||||||
|
.Include(e => e.Department)
|
||||||
|
.Include(e => e.Region)
|
||||||
|
.Include(e => e.Emails)
|
||||||
|
.Include(e => e.Phones)
|
||||||
|
.Where(e => !e.IsDeleted.HasValue || e.IsDeleted == false);
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(search))
|
if (!string.IsNullOrWhiteSpace(search))
|
||||||
{
|
{
|
||||||
query = query.Where(e => (e.FirstName + " " + e.LastName).Contains(search));
|
var s = search.ToLower();
|
||||||
|
query = query.Where(e =>
|
||||||
|
(e.FirstName != null && e.FirstName.ToLower().Contains(s)) ||
|
||||||
|
(e.LastName != null && e.LastName.ToLower().Contains(s)) ||
|
||||||
|
e.Emails.Any(x => x.Address != null && x.Address.ToLower().Contains(s)) ||
|
||||||
|
e.Phones.Any(x => x.Number != null && x.Number.Contains(search))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalCount = await query.CountAsync();
|
var totalCount = await query.CountAsync();
|
||||||
var items = await query
|
var items = await query
|
||||||
.OrderBy(e => e.LastName)
|
.OrderByDescending(e => e.Id)
|
||||||
.Skip((page - 1) * pageSize)
|
.Skip((page - 1) * pageSize)
|
||||||
.Take(pageSize)
|
.Take(pageSize)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,10 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
public async Task<FollowUps?> GetByIdWithDetailsAsync(int id)
|
public async Task<FollowUps?> GetByIdWithDetailsAsync(int id)
|
||||||
{
|
{
|
||||||
return await _context.FollowUps
|
return await _context.FollowUps
|
||||||
|
.Include(x => x.Employee)
|
||||||
|
.Include(x => x.Account)
|
||||||
|
.Include(x => x.Location)
|
||||||
|
// Removed .Include(x => x.WorkOrder) due to schema mismatch - WorkOrder has columns not in DB
|
||||||
.FirstOrDefaultAsync(f => f.Id == id);
|
.FirstOrDefaultAsync(f => f.Id == id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,21 +48,37 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(IEnumerable<FollowUps> Items, int TotalCount)> GetPagedAsync(
|
public async Task<(IEnumerable<FollowUps> Items, int TotalCount)> GetPagedAsync(
|
||||||
int page,
|
int page,
|
||||||
int pageSize,
|
int pageSize,
|
||||||
string? search = null,
|
string? search = null,
|
||||||
string? status = null)
|
string? status = null)
|
||||||
{
|
{
|
||||||
var query = _context.FollowUps.AsQueryable();
|
search ??= "";
|
||||||
|
status = string.IsNullOrWhiteSpace(status) ? "Open" : status;
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(status))
|
var query = _context.FollowUps
|
||||||
|
.Include(x => x.Employee)
|
||||||
|
.Include(x => x.Account)
|
||||||
|
.Include(x => x.Location)
|
||||||
|
// Removed .Include(x => x.WorkOrder) due to schema mismatch - WorkOrder has columns not in DB
|
||||||
|
.Where(x => x.Status == status);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(search))
|
||||||
{
|
{
|
||||||
query = query.Where(f => f.Status == status);
|
var s = search.ToLower();
|
||||||
|
query = query.Where(x =>
|
||||||
|
(x.Reason ?? "").ToLower().Contains(s) ||
|
||||||
|
(x.Account != null && (x.Account.Name ?? "").ToLower().Contains(s)) ||
|
||||||
|
(x.Employee != null &&
|
||||||
|
(((x.Employee.FirstName ?? "") + " " + (x.Employee.LastName ?? ""))
|
||||||
|
.ToLower().Contains(s))
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalCount = await query.CountAsync();
|
var totalCount = await query.CountAsync();
|
||||||
var items = await query
|
var items = await query
|
||||||
.OrderByDescending(f => f.CreatedDate)
|
.OrderByDescending(f => f.Id)
|
||||||
.Skip((page - 1) * pageSize)
|
.Skip((page - 1) * pageSize)
|
||||||
.Take(pageSize)
|
.Take(pageSize)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
|
||||||
|
|
@ -94,5 +94,39 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
{
|
{
|
||||||
return await _context.Locations.CountAsync();
|
return await _context.Locations.CountAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<(IEnumerable<object> Items, int TotalCount)> GetAddressbookPagedAsync(
|
||||||
|
int page,
|
||||||
|
int pageSize,
|
||||||
|
string? search = null)
|
||||||
|
{
|
||||||
|
search ??= "";
|
||||||
|
|
||||||
|
var query = _context.Locations.AsQueryable();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(search))
|
||||||
|
{
|
||||||
|
var s = search.ToLower();
|
||||||
|
query = query.Where(w =>
|
||||||
|
(w.Name ?? "").ToLower().Contains(s) ||
|
||||||
|
(w.Title ?? "").ToLower().Contains(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalCount = await query.CountAsync();
|
||||||
|
|
||||||
|
var data = await query
|
||||||
|
.Select(n => new
|
||||||
|
{
|
||||||
|
n.Id,
|
||||||
|
n.Name,
|
||||||
|
n.Title
|
||||||
|
})
|
||||||
|
.OrderByDescending(d => d.Id)
|
||||||
|
.Skip((page - 1) * pageSize)
|
||||||
|
.Take(pageSize)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return (data, totalCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,15 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
return await _context.PMSchedules.ToListAsync();
|
return await _context.PMSchedules.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<PMSchedules>> GetAllWithDetailsAsync()
|
||||||
|
{
|
||||||
|
return await _context.PMSchedules
|
||||||
|
.Include(x => x.Asset)
|
||||||
|
.Include(x => x.Location)
|
||||||
|
.OrderByDescending(x => x.Id)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<PMSchedules>> GetByLocationIdAsync(int locationId)
|
public async Task<IEnumerable<PMSchedules>> GetByLocationIdAsync(int locationId)
|
||||||
{
|
{
|
||||||
return await _context.PMSchedules
|
return await _context.PMSchedules
|
||||||
|
|
|
||||||
|
|
@ -30,15 +30,27 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(IEnumerable<Vendor> Items, int TotalCount)> GetPagedAsync(
|
public async Task<(IEnumerable<Vendor> Items, int TotalCount)> GetPagedAsync(
|
||||||
int page,
|
int page,
|
||||||
int pageSize,
|
int pageSize,
|
||||||
string? search = null)
|
string? search = null)
|
||||||
{
|
{
|
||||||
var query = _context.Vendors.AsQueryable();
|
search ??= "";
|
||||||
|
|
||||||
|
var query = _context.Vendors.Where(v => v.IsActive);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(search))
|
||||||
|
{
|
||||||
|
var s = search.ToLower();
|
||||||
|
query = query.Where(v =>
|
||||||
|
(v.CompanyName ?? "").ToLower().Contains(s) ||
|
||||||
|
(v.ContactName ?? "").ToLower().Contains(s) ||
|
||||||
|
(v.Email ?? "").ToLower().Contains(s) ||
|
||||||
|
(v.TradeSpecialties ?? "").ToLower().Contains(s));
|
||||||
|
}
|
||||||
|
|
||||||
var totalCount = await query.CountAsync();
|
var totalCount = await query.CountAsync();
|
||||||
var items = await query
|
var items = await query
|
||||||
.OrderBy(v => v.Id)
|
.OrderByDescending(v => v.Id)
|
||||||
.Skip((page - 1) * pageSize)
|
.Skip((page - 1) * pageSize)
|
||||||
.Take(pageSize)
|
.Take(pageSize)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
|
||||||
|
|
@ -66,18 +66,18 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(IEnumerable<WorkOrder> Items, int TotalCount)> GetPagedAsync(
|
public async Task<(IEnumerable<WorkOrder> Items, int TotalCount)> GetPagedAsync(
|
||||||
int page,
|
int page,
|
||||||
int pageSize,
|
int pageSize,
|
||||||
string? search = null,
|
string? search = null,
|
||||||
string? status = null,
|
string? status = null,
|
||||||
string? priority = null)
|
string? priority = null)
|
||||||
{
|
{
|
||||||
var query = _context.workOrders.AsQueryable();
|
var query = _context.workOrders.AsQueryable();
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(search))
|
if (!string.IsNullOrWhiteSpace(search))
|
||||||
{
|
{
|
||||||
query = query.Where(w =>
|
query = query.Where(w =>
|
||||||
w.WorkerOrderNumber!.Contains(search) ||
|
w.WorkerOrderNumber!.Contains(search) ||
|
||||||
w.WorkerOrderTitle!.Contains(search));
|
w.WorkerOrderTitle!.Contains(search));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,6 +101,91 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
return (items, totalCount);
|
return (items, totalCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<(IEnumerable<object> Items, int TotalCount)> GetWorkOrderListPagedAsync(
|
||||||
|
int page,
|
||||||
|
int pageSize,
|
||||||
|
string? search = null,
|
||||||
|
string? status = null,
|
||||||
|
string? assignee = null,
|
||||||
|
int? locationId = null,
|
||||||
|
string? sortBy = "lastUpdated",
|
||||||
|
string? sortDir = "desc")
|
||||||
|
{
|
||||||
|
search ??= "";
|
||||||
|
|
||||||
|
var query = _context.workOrders
|
||||||
|
.Include(w => w.Locations)
|
||||||
|
.Include(w => w.AssignToUser)
|
||||||
|
.Where(w => w.istemplate != true);
|
||||||
|
|
||||||
|
if (locationId.HasValue)
|
||||||
|
query = query.Where(w => w.LocationId == locationId.Value);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(status))
|
||||||
|
query = query.Where(w => w.Status == status);
|
||||||
|
|
||||||
|
if (assignee == "__unassigned")
|
||||||
|
query = query.Where(w => w.AssignTo == null || w.AssignTo == "");
|
||||||
|
else if (!string.IsNullOrWhiteSpace(assignee))
|
||||||
|
query = query.Where(w => w.AssignToUser != null && (w.AssignToUser.FirstName + " " + w.AssignToUser.LastName).Contains(assignee));
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(search))
|
||||||
|
{
|
||||||
|
var s = search.ToLower();
|
||||||
|
query = query.Where(w =>
|
||||||
|
(w.InternalWONumber ?? "").ToLower().Contains(s) ||
|
||||||
|
(w.WorkerOrderNumber ?? "").ToLower().Contains(s) ||
|
||||||
|
(w.WorkerOrderTitle ?? "").ToLower().Contains(s) ||
|
||||||
|
(w.Locations.Title ?? "").ToLower().Contains(s) ||
|
||||||
|
(w.Locations.Name ?? "").ToLower().Contains(s)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalCount = await query.CountAsync();
|
||||||
|
|
||||||
|
var isAsc = sortDir?.ToLower() == "asc";
|
||||||
|
IOrderedQueryable<WorkOrder> ordered = (sortBy?.ToLower()) switch
|
||||||
|
{
|
||||||
|
"number" => isAsc ? query.OrderBy(w => w.InternalWONumber) : query.OrderByDescending(w => w.InternalWONumber),
|
||||||
|
"title" => isAsc ? query.OrderBy(w => w.WorkerOrderTitle) : query.OrderByDescending(w => w.WorkerOrderTitle),
|
||||||
|
"location" => isAsc ? query.OrderBy(w => w.Locations != null ? w.Locations.Name : "") : query.OrderByDescending(w => w.Locations != null ? w.Locations.Name : ""),
|
||||||
|
"priority" => isAsc ? query.OrderBy(w => w.Priority) : query.OrderByDescending(w => w.Priority),
|
||||||
|
"status" => isAsc ? query.OrderBy(w => w.Status) : query.OrderByDescending(w => w.Status),
|
||||||
|
"createddate" => isAsc ? query.OrderBy(w => w.CreatedDate) : query.OrderByDescending(w => w.CreatedDate),
|
||||||
|
"assignedto" => isAsc ? query.OrderBy(w => w.AssignToUser != null ? w.AssignToUser.FirstName : "") : query.OrderByDescending(w => w.AssignToUser != null ? w.AssignToUser.FirstName : ""),
|
||||||
|
"lastupdated" => isAsc ? query.OrderBy(w => w.LastModificationTime) : query.OrderByDescending(w => w.LastModificationTime),
|
||||||
|
_ => query.OrderByDescending(w => w.Id)
|
||||||
|
};
|
||||||
|
|
||||||
|
var data = await ordered
|
||||||
|
.Skip((page - 1) * pageSize)
|
||||||
|
.Take(pageSize)
|
||||||
|
.Select(w => new
|
||||||
|
{
|
||||||
|
id = w.Id,
|
||||||
|
internalWONumber = w.InternalWONumber,
|
||||||
|
workOrderNumber = w.WorkerOrderNumber,
|
||||||
|
number = w.InternalWONumber ?? w.WorkerOrderNumber,
|
||||||
|
title = w.WorkerOrderTitle,
|
||||||
|
location = w.Locations != null ? w.Locations.Name : "",
|
||||||
|
locationName = w.Locations != null ? w.Locations.Name : "",
|
||||||
|
priority = w.Priority,
|
||||||
|
status = w.Status,
|
||||||
|
createdDate = w.CreatedDate,
|
||||||
|
dueDate = w.DueDate,
|
||||||
|
assignedTo = w.AssignToUser != null ? w.AssignToUser.FirstName + " " + w.AssignToUser.LastName : "",
|
||||||
|
employeeName = w.AssignToUser != null ? w.AssignToUser.FirstName + " " + w.AssignToUser.LastName : "",
|
||||||
|
lastUpdated = new[] {
|
||||||
|
w.LastModificationTime,
|
||||||
|
w.Comments.Max(c => (DateTime?)c.CreatedDate),
|
||||||
|
_context.WorkOrderAuditLogs.Where(a => a.WorkOrderId == w.Id).Max(a => (DateTime?)a.CreatedAt)
|
||||||
|
}.Where(d => d.HasValue).Max()
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return (data, totalCount);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<WorkOrder> AddAsync(WorkOrder workOrder)
|
public async Task<WorkOrder> AddAsync(WorkOrder workOrder)
|
||||||
{
|
{
|
||||||
workOrder.CreatedDate = DateTime.Now;
|
workOrder.CreatedDate = DateTime.Now;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,13 @@ namespace SeaHaven.DataServices.Interfaces
|
||||||
Task<Locations?> GetByIdWithDetailsAsync(int id);
|
Task<Locations?> GetByIdWithDetailsAsync(int id);
|
||||||
Task<IEnumerable<Locations>> GetAllAsync();
|
Task<IEnumerable<Locations>> GetAllAsync();
|
||||||
Task<IEnumerable<Locations>> GetByAccountIdAsync(int accountId);
|
Task<IEnumerable<Locations>> GetByAccountIdAsync(int accountId);
|
||||||
|
|
||||||
|
// Paged results returning DTOs
|
||||||
Task<(IEnumerable<Locations> Items, int TotalCount)> GetPagedAsync(int page, int pageSize, string? search = null);
|
Task<(IEnumerable<Locations> Items, int TotalCount)> GetPagedAsync(int page, int pageSize, string? search = null);
|
||||||
|
|
||||||
|
// For addressbook endpoint - returns simplified DTO
|
||||||
|
Task<(IEnumerable<object> Items, int TotalCount)> GetAddressbookPagedAsync(int page, int pageSize, string? search = null);
|
||||||
|
|
||||||
Task<Locations> AddAsync(Locations location);
|
Task<Locations> AddAsync(Locations location);
|
||||||
Task UpdateAsync(Locations location);
|
Task UpdateAsync(Locations location);
|
||||||
Task DeleteAsync(int id);
|
Task DeleteAsync(int id);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ namespace SeaHaven.DataServices.Interfaces
|
||||||
Task<PMSchedules?> GetByIdAsync(int id);
|
Task<PMSchedules?> GetByIdAsync(int id);
|
||||||
Task<PMSchedules?> GetByIdWithDetailsAsync(int id);
|
Task<PMSchedules?> GetByIdWithDetailsAsync(int id);
|
||||||
Task<IEnumerable<PMSchedules>> GetAllAsync();
|
Task<IEnumerable<PMSchedules>> GetAllAsync();
|
||||||
|
Task<IEnumerable<PMSchedules>> GetAllWithDetailsAsync();
|
||||||
Task<IEnumerable<PMSchedules>> GetByLocationIdAsync(int locationId);
|
Task<IEnumerable<PMSchedules>> GetByLocationIdAsync(int locationId);
|
||||||
Task<(IEnumerable<PMSchedules> Items, int TotalCount)> GetPagedAsync(int page, int pageSize, string? search = null);
|
Task<(IEnumerable<PMSchedules> Items, int TotalCount)> GetPagedAsync(int page, int pageSize, string? search = null);
|
||||||
Task<PMSchedules> AddAsync(PMSchedules pmSchedule);
|
Task<PMSchedules> AddAsync(PMSchedules pmSchedule);
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,22 @@ namespace SeaHaven.DataServices.Interfaces
|
||||||
|
|
||||||
// Paged results
|
// Paged results
|
||||||
Task<(IEnumerable<WorkOrder> Items, int TotalCount)> GetPagedAsync(
|
Task<(IEnumerable<WorkOrder> Items, int TotalCount)> GetPagedAsync(
|
||||||
int page,
|
int page,
|
||||||
int pageSize,
|
int pageSize,
|
||||||
string? search = null,
|
string? search = null,
|
||||||
string? status = null,
|
string? status = null,
|
||||||
string? priority = null);
|
string? priority = null);
|
||||||
|
|
||||||
|
// Paged list with detailed information (for GetWorkOrderList endpoint)
|
||||||
|
Task<(IEnumerable<object> Items, int TotalCount)> GetWorkOrderListPagedAsync(
|
||||||
|
int page,
|
||||||
|
int pageSize,
|
||||||
|
string? search = null,
|
||||||
|
string? status = null,
|
||||||
|
string? assignee = null,
|
||||||
|
int? locationId = null,
|
||||||
|
string? sortBy = "lastUpdated",
|
||||||
|
string? sortDir = "desc");
|
||||||
|
|
||||||
// Command operations
|
// Command operations
|
||||||
Task<WorkOrder> AddAsync(WorkOrder workOrder);
|
Task<WorkOrder> AddAsync(WorkOrder workOrder);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ namespace SeaHaven.Services.DTOs
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
public string? Type { get; set; }
|
||||||
public string? Phone { get; set; }
|
public string? Phone { get; set; }
|
||||||
public string? Email { get; set; }
|
public string? Email { get; set; }
|
||||||
public string? Website { get; set; }
|
public string? Website { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,6 @@ namespace SeaHaven.Services.DTOs
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
public string? Type { get; set; }
|
|
||||||
public string? SerialNumber { get; set; }
|
|
||||||
public int? LocationId { get; set; }
|
public int? LocationId { get; set; }
|
||||||
public string? LocationName { get; set; }
|
public string? LocationName { get; set; }
|
||||||
public DateTime? CreatedDate { get; set; }
|
public DateTime? CreatedDate { get; set; }
|
||||||
|
|
@ -14,16 +12,12 @@ namespace SeaHaven.Services.DTOs
|
||||||
public class CreateAssetDTO
|
public class CreateAssetDTO
|
||||||
{
|
{
|
||||||
public required string Name { get; set; }
|
public required string Name { get; set; }
|
||||||
public string? Type { get; set; }
|
|
||||||
public string? SerialNumber { get; set; }
|
|
||||||
public int? LocationId { get; set; }
|
public int? LocationId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UpdateAssetDTO
|
public class UpdateAssetDTO
|
||||||
{
|
{
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
public string? Type { get; set; }
|
|
||||||
public string? SerialNumber { get; set; }
|
|
||||||
public int? LocationId { get; set; }
|
public int? LocationId { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,32 +3,41 @@ namespace SeaHaven.Services.DTOs
|
||||||
public class FollowUpDTO
|
public class FollowUpDTO
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string? Subject { get; set; }
|
public string? Reason { get; set; }
|
||||||
public string? Description { get; set; }
|
public DateTime ScheduleDate { get; set; }
|
||||||
|
public TimeSpan ScheduleStartTime { get; set; }
|
||||||
public string? Status { get; set; }
|
public string? Status { get; set; }
|
||||||
|
public int? EmployeeId { get; set; }
|
||||||
|
public string? EmployeeName { get; set; }
|
||||||
public int? WorkOrderId { get; set; }
|
public int? WorkOrderId { get; set; }
|
||||||
public string? AssignedTo { get; set; }
|
public int? AccountId { get; set; }
|
||||||
public DateTime? DueDate { get; set; }
|
public string? AccountName { get; set; }
|
||||||
|
public int? LocationId { get; set; }
|
||||||
|
public string? LocationName { get; set; }
|
||||||
public DateTime? CreatedDate { get; set; }
|
public DateTime? CreatedDate { get; set; }
|
||||||
public string? CreatedBy { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CreateFollowUpDTO
|
public class CreateFollowUpDTO
|
||||||
{
|
{
|
||||||
public required string Subject { get; set; }
|
public required string Reason { get; set; }
|
||||||
public string? Description { get; set; }
|
public DateTime ScheduleDate { get; set; }
|
||||||
public string? Status { get; set; }
|
public TimeSpan ScheduleStartTime { get; set; }
|
||||||
|
public required string Status { get; set; }
|
||||||
|
public int? EmployeeId { get; set; }
|
||||||
public int? WorkOrderId { get; set; }
|
public int? WorkOrderId { get; set; }
|
||||||
public string? AssignedTo { get; set; }
|
public int? AccountId { get; set; }
|
||||||
public DateTime? DueDate { get; set; }
|
public int? LocationId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UpdateFollowUpDTO
|
public class UpdateFollowUpDTO
|
||||||
{
|
{
|
||||||
public string? Subject { get; set; }
|
public string? Reason { get; set; }
|
||||||
public string? Description { get; set; }
|
public DateTime? ScheduleDate { get; set; }
|
||||||
|
public TimeSpan? ScheduleStartTime { get; set; }
|
||||||
public string? Status { get; set; }
|
public string? Status { get; set; }
|
||||||
public string? AssignedTo { get; set; }
|
public int? EmployeeId { get; set; }
|
||||||
public DateTime? DueDate { get; set; }
|
public int? WorkOrderId { get; set; }
|
||||||
|
public int? AccountId { get; set; }
|
||||||
|
public int? LocationId { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,16 @@ namespace SeaHaven.Services.DTOs
|
||||||
public class LocationDTO
|
public class LocationDTO
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string? LocationName { get; set; }
|
public string? Name { get; set; }
|
||||||
public string? Address { get; set; }
|
public string? Title { get; set; }
|
||||||
|
public string? Address1 { get; set; }
|
||||||
|
public string? Address2 { get; set; }
|
||||||
public string? City { get; set; }
|
public string? City { get; set; }
|
||||||
public string? State { get; set; }
|
public string? State { get; set; }
|
||||||
public string? Zipcode { get; set; }
|
public string? Zip { get; set; }
|
||||||
public int? AccountId { get; set; }
|
public string? PhoneNumber { get; set; }
|
||||||
public string? AccountName { get; set; }
|
public string? Email { get; set; }
|
||||||
|
public string? Status { get; set; }
|
||||||
public DateTime? CreatedDate { get; set; }
|
public DateTime? CreatedDate { get; set; }
|
||||||
public string? CreatedBy { get; set; }
|
public string? CreatedBy { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,29 +4,33 @@ namespace SeaHaven.Services.DTOs
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
public string? Description { get; set; }
|
public string? Frequency { get; set; }
|
||||||
|
public DateTime StartDate { get; set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
public int? AssetId { get; set; }
|
||||||
|
public string? AssetName { get; set; }
|
||||||
public int? LocationId { get; set; }
|
public int? LocationId { get; set; }
|
||||||
public string? LocationName { get; set; }
|
public string? LocationName { get; set; }
|
||||||
public string? Frequency { get; set; }
|
|
||||||
public DateTime? NextDueDate { get; set; }
|
|
||||||
public DateTime? CreatedDate { get; set; }
|
public DateTime? CreatedDate { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CreatePMScheduleDTO
|
public class CreatePMScheduleDTO
|
||||||
{
|
{
|
||||||
public required string Name { get; set; }
|
public required string Name { get; set; }
|
||||||
public string? Description { get; set; }
|
public required string Frequency { get; set; }
|
||||||
|
public DateTime StartDate { get; set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
public int? AssetId { get; set; }
|
||||||
public int? LocationId { get; set; }
|
public int? LocationId { get; set; }
|
||||||
public string? Frequency { get; set; }
|
|
||||||
public DateTime? NextDueDate { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UpdatePMScheduleDTO
|
public class UpdatePMScheduleDTO
|
||||||
{
|
{
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
public string? Description { get; set; }
|
|
||||||
public int? LocationId { get; set; }
|
|
||||||
public string? Frequency { get; set; }
|
public string? Frequency { get; set; }
|
||||||
public DateTime? NextDueDate { get; set; }
|
public DateTime? StartDate { get; set; }
|
||||||
|
public bool? IsActive { get; set; }
|
||||||
|
public int? AssetId { get; set; }
|
||||||
|
public int? LocationId { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
124
SeaHaven.Services/Implementation/AccountService.cs
Normal file
124
SeaHaven.Services/Implementation/AccountService.cs
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
using Data.SeaHavenIndustries;
|
||||||
|
using SeaHaven.DataServices.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace SeaHaven.Services.Implementation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Account service implementation
|
||||||
|
/// Contains business logic, validation, and orchestration for Account operations
|
||||||
|
/// </summary>
|
||||||
|
public class AccountService : IAccountService
|
||||||
|
{
|
||||||
|
private readonly IAccountDataService _accountDataService;
|
||||||
|
|
||||||
|
public AccountService(IAccountDataService accountDataService)
|
||||||
|
{
|
||||||
|
_accountDataService = accountDataService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AccountDTO?> GetAccountByIdAsync(int id)
|
||||||
|
{
|
||||||
|
var account = await _accountDataService.GetByIdAsync(id);
|
||||||
|
return account == null ? null : MapToDTO(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AccountDTO?> GetAccountByIdWithDetailsAsync(int id)
|
||||||
|
{
|
||||||
|
var account = await _accountDataService.GetByIdWithDetailsAsync(id);
|
||||||
|
return account == null ? null : MapToDTO(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<AccountDTO>> GetAllAccountsAsync()
|
||||||
|
{
|
||||||
|
var accounts = await _accountDataService.GetAllAsync();
|
||||||
|
return accounts.Select(MapToDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PagedResult<AccountDTO>> GetAccountsPagedAsync(int page, int pageSize, string? search = null)
|
||||||
|
{
|
||||||
|
var (items, totalCount) = await _accountDataService.GetPagedAsync(page, pageSize, search);
|
||||||
|
return new PagedResult<AccountDTO>
|
||||||
|
{
|
||||||
|
Items = items.Select(MapToDTO).ToList(),
|
||||||
|
TotalCount = totalCount,
|
||||||
|
Page = page,
|
||||||
|
PageSize = pageSize
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AccountDTO> CreateAccountAsync(CreateAccountDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var account = new Accounts
|
||||||
|
{
|
||||||
|
Name = dto.Name,
|
||||||
|
Phone = dto.Phone,
|
||||||
|
Email = dto.Email,
|
||||||
|
Website = dto.Website,
|
||||||
|
CreatedDate = DateTime.UtcNow,
|
||||||
|
createdby = userId
|
||||||
|
};
|
||||||
|
|
||||||
|
var created = await _accountDataService.AddAsync(account);
|
||||||
|
return MapToDTO(created);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AccountDTO> UpdateAccountAsync(int id, UpdateAccountDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var account = await _accountDataService.GetByIdAsync(id);
|
||||||
|
if (account == null)
|
||||||
|
throw new InvalidOperationException($"Account with ID {id} not found");
|
||||||
|
|
||||||
|
if (dto.Name != null) account.Name = dto.Name;
|
||||||
|
if (dto.Phone != null) account.Phone = dto.Phone;
|
||||||
|
if (dto.Email != null) account.Email = dto.Email;
|
||||||
|
if (dto.Website != null) account.Website = dto.Website;
|
||||||
|
|
||||||
|
account.LastModificationTime = DateTime.UtcNow;
|
||||||
|
if (int.TryParse(userId, out int userIdInt))
|
||||||
|
account.LastModifierUserId = userIdInt;
|
||||||
|
|
||||||
|
await _accountDataService.UpdateAsync(account);
|
||||||
|
return MapToDTO(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteAccountAsync(int id, string userId)
|
||||||
|
{
|
||||||
|
var account = await _accountDataService.GetByIdAsync(id);
|
||||||
|
if (account == null)
|
||||||
|
throw new InvalidOperationException($"Account with ID {id} not found");
|
||||||
|
|
||||||
|
account.IsDeleted = true;
|
||||||
|
account.DeleterUserId = userId;
|
||||||
|
account.DeletionTime = DateTime.UtcNow;
|
||||||
|
|
||||||
|
await _accountDataService.UpdateAsync(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> AccountExistsAsync(int id)
|
||||||
|
{
|
||||||
|
return await _accountDataService.ExistsAsync(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetTotalAccountCountAsync()
|
||||||
|
{
|
||||||
|
return await _accountDataService.CountAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private AccountDTO MapToDTO(Accounts account)
|
||||||
|
{
|
||||||
|
return new AccountDTO
|
||||||
|
{
|
||||||
|
Id = account.Id,
|
||||||
|
Name = account.Name,
|
||||||
|
Type = account.Type,
|
||||||
|
Phone = account.Phone,
|
||||||
|
Email = account.Email,
|
||||||
|
Website = account.Website,
|
||||||
|
CreatedDate = account.CreatedDate,
|
||||||
|
CreatedBy = account.createdby
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
123
SeaHaven.Services/Implementation/AssetService.cs
Normal file
123
SeaHaven.Services/Implementation/AssetService.cs
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
using Data.SeaHavenIndustries;
|
||||||
|
using SeaHaven.DataServices.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace SeaHaven.Services.Implementation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Asset service implementation
|
||||||
|
/// Contains business logic, validation, and orchestration for Asset operations
|
||||||
|
/// </summary>
|
||||||
|
public class AssetService : IAssetService
|
||||||
|
{
|
||||||
|
private readonly IAssetDataService _assetDataService;
|
||||||
|
|
||||||
|
public AssetService(IAssetDataService assetDataService)
|
||||||
|
{
|
||||||
|
_assetDataService = assetDataService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AssetDTO?> GetAssetByIdAsync(int id)
|
||||||
|
{
|
||||||
|
var asset = await _assetDataService.GetByIdAsync(id);
|
||||||
|
return asset == null ? null : MapToDTO(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AssetDTO?> GetAssetByIdWithDetailsAsync(int id)
|
||||||
|
{
|
||||||
|
var asset = await _assetDataService.GetByIdWithDetailsAsync(id);
|
||||||
|
return asset == null ? null : MapToDTO(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<AssetDTO>> GetAllAssetsAsync()
|
||||||
|
{
|
||||||
|
var assets = await _assetDataService.GetAllAsync();
|
||||||
|
return assets.Select(MapToDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<AssetDTO>> GetAssetsByLocationIdAsync(int locationId)
|
||||||
|
{
|
||||||
|
var assets = await _assetDataService.GetAllAsync();
|
||||||
|
return assets.Where(a => a.LocationId == locationId).Select(MapToDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PagedResult<AssetDTO>> GetAssetsPagedAsync(int page, int pageSize, string? search = null)
|
||||||
|
{
|
||||||
|
var (items, totalCount) = await _assetDataService.GetPagedAsync(page, pageSize, search);
|
||||||
|
return new PagedResult<AssetDTO>
|
||||||
|
{
|
||||||
|
Items = items.Select(MapToDTO).ToList(),
|
||||||
|
TotalCount = totalCount,
|
||||||
|
Page = page,
|
||||||
|
PageSize = pageSize
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AssetDTO> CreateAssetAsync(CreateAssetDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var asset = new Assets
|
||||||
|
{
|
||||||
|
Name = dto.Name,
|
||||||
|
LocationId = dto.LocationId,
|
||||||
|
CreatedDate = DateTime.UtcNow,
|
||||||
|
createdby = userId
|
||||||
|
};
|
||||||
|
|
||||||
|
var created = await _assetDataService.AddAsync(asset);
|
||||||
|
return MapToDTO(created);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AssetDTO> UpdateAssetAsync(int id, UpdateAssetDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var asset = await _assetDataService.GetByIdAsync(id);
|
||||||
|
if (asset == null)
|
||||||
|
throw new InvalidOperationException($"Asset with ID {id} not found");
|
||||||
|
|
||||||
|
if (dto.Name != null) asset.Name = dto.Name;
|
||||||
|
if (dto.LocationId.HasValue) asset.LocationId = dto.LocationId;
|
||||||
|
|
||||||
|
asset.LastModificationTime = DateTime.UtcNow;
|
||||||
|
if (int.TryParse(userId, out int userIdInt))
|
||||||
|
asset.LastModifierUserId = userIdInt;
|
||||||
|
|
||||||
|
await _assetDataService.UpdateAsync(asset);
|
||||||
|
return MapToDTO(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteAssetAsync(int id, string userId)
|
||||||
|
{
|
||||||
|
var asset = await _assetDataService.GetByIdAsync(id);
|
||||||
|
if (asset == null)
|
||||||
|
throw new InvalidOperationException($"Asset with ID {id} not found");
|
||||||
|
|
||||||
|
asset.IsDeleted = true;
|
||||||
|
asset.DeleterUserId = userId;
|
||||||
|
asset.DeletionTime = DateTime.UtcNow;
|
||||||
|
|
||||||
|
await _assetDataService.UpdateAsync(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> AssetExistsAsync(int id)
|
||||||
|
{
|
||||||
|
return await _assetDataService.ExistsAsync(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetTotalAssetCountAsync()
|
||||||
|
{
|
||||||
|
return await _assetDataService.CountAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private AssetDTO MapToDTO(Assets asset)
|
||||||
|
{
|
||||||
|
return new AssetDTO
|
||||||
|
{
|
||||||
|
Id = asset.Id,
|
||||||
|
Name = asset.Name,
|
||||||
|
LocationId = asset.LocationId,
|
||||||
|
LocationName = asset.Location?.Name,
|
||||||
|
CreatedDate = asset.CreatedDate
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
139
SeaHaven.Services/Implementation/DispatchService.cs
Normal file
139
SeaHaven.Services/Implementation/DispatchService.cs
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
using Data.SeaHavenIndustries;
|
||||||
|
using SeaHaven.DataServices.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace SeaHaven.Services.Implementation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Dispatch service implementation
|
||||||
|
/// Contains business logic, validation, and orchestration for Dispatch operations
|
||||||
|
/// </summary>
|
||||||
|
public class DispatchService : IDispatchService
|
||||||
|
{
|
||||||
|
private readonly IDispatchDataService _dispatchDataService;
|
||||||
|
|
||||||
|
public DispatchService(IDispatchDataService dispatchDataService)
|
||||||
|
{
|
||||||
|
_dispatchDataService = dispatchDataService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<DispatchDTO?> GetDispatchByIdAsync(int id)
|
||||||
|
{
|
||||||
|
var dispatch = await _dispatchDataService.GetByIdAsync(id);
|
||||||
|
return dispatch == null ? null : MapToDTO(dispatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<DispatchDTO?> GetDispatchByIdWithDetailsAsync(int id)
|
||||||
|
{
|
||||||
|
var dispatch = await _dispatchDataService.GetByIdWithDetailsAsync(id);
|
||||||
|
return dispatch == null ? null : MapToDTO(dispatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<DispatchDTO>> GetAllDispatchesAsync()
|
||||||
|
{
|
||||||
|
var dispatches = await _dispatchDataService.GetAllAsync();
|
||||||
|
return dispatches.Select(MapToDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<DispatchDTO>> GetDispatchesByVendorIdAsync(int vendorId)
|
||||||
|
{
|
||||||
|
var dispatches = await _dispatchDataService.GetByVendorIdAsync(vendorId);
|
||||||
|
return dispatches.Select(MapToDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PagedResult<DispatchDTO>> GetDispatchesPagedAsync(int page, int pageSize, string? search = null, string? status = null)
|
||||||
|
{
|
||||||
|
var (items, totalCount) = await _dispatchDataService.GetPagedAsync(page, pageSize, search, status);
|
||||||
|
return new PagedResult<DispatchDTO>
|
||||||
|
{
|
||||||
|
Items = items.Select(MapToDTO).ToList(),
|
||||||
|
TotalCount = totalCount,
|
||||||
|
Page = page,
|
||||||
|
PageSize = pageSize
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<DispatchDTO> CreateDispatchAsync(CreateDispatchDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var dispatchNumber = await GenerateNextDispatchNumberAsync();
|
||||||
|
|
||||||
|
var dispatch = new Dispatch
|
||||||
|
{
|
||||||
|
VendorId = dto.VendorId,
|
||||||
|
ScheduledDate = dto.ScheduledDate,
|
||||||
|
Status = dto.Status ?? "Pending",
|
||||||
|
DispatchNumber = dispatchNumber,
|
||||||
|
CreatedDate = DateTime.UtcNow,
|
||||||
|
createdby = userId
|
||||||
|
};
|
||||||
|
|
||||||
|
var created = await _dispatchDataService.AddAsync(dispatch);
|
||||||
|
return MapToDTO(created);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<DispatchDTO> UpdateDispatchAsync(int id, UpdateDispatchDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var dispatch = await _dispatchDataService.GetByIdAsync(id);
|
||||||
|
if (dispatch == null)
|
||||||
|
throw new InvalidOperationException($"Dispatch with ID {id} not found");
|
||||||
|
|
||||||
|
if (dto.VendorId.HasValue) dispatch.VendorId = dto.VendorId.Value;
|
||||||
|
if (dto.ScheduledDate.HasValue) dispatch.ScheduledDate = dto.ScheduledDate;
|
||||||
|
if (dto.CompletedDate.HasValue) dispatch.CompletedDate = dto.CompletedDate;
|
||||||
|
if (dto.Status != null) dispatch.Status = dto.Status;
|
||||||
|
|
||||||
|
dispatch.LastModificationTime = DateTime.UtcNow;
|
||||||
|
if (int.TryParse(userId, out int userIdInt))
|
||||||
|
dispatch.LastModifierUserId = userIdInt;
|
||||||
|
|
||||||
|
await _dispatchDataService.UpdateAsync(dispatch);
|
||||||
|
return MapToDTO(dispatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteDispatchAsync(int id, string userId)
|
||||||
|
{
|
||||||
|
var dispatch = await _dispatchDataService.GetByIdAsync(id);
|
||||||
|
if (dispatch == null)
|
||||||
|
throw new InvalidOperationException($"Dispatch with ID {id} not found");
|
||||||
|
|
||||||
|
dispatch.IsDeleted = true;
|
||||||
|
dispatch.DeleterUserId = userId;
|
||||||
|
dispatch.DeletionTime = DateTime.UtcNow;
|
||||||
|
|
||||||
|
await _dispatchDataService.UpdateAsync(dispatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> DispatchExistsAsync(int id)
|
||||||
|
{
|
||||||
|
return await _dispatchDataService.ExistsAsync(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GenerateNextDispatchNumberAsync()
|
||||||
|
{
|
||||||
|
var count = await _dispatchDataService.CountAsync();
|
||||||
|
return $"DISP-{(count + 1):D6}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetTotalDispatchCountAsync()
|
||||||
|
{
|
||||||
|
return await _dispatchDataService.CountAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private DispatchDTO MapToDTO(Dispatch dispatch)
|
||||||
|
{
|
||||||
|
return new DispatchDTO
|
||||||
|
{
|
||||||
|
Id = dispatch.Id,
|
||||||
|
DispatchNumber = dispatch.DispatchNumber,
|
||||||
|
Status = dispatch.Status,
|
||||||
|
VendorId = dispatch.VendorId,
|
||||||
|
VendorName = dispatch.Vendor?.CompanyName,
|
||||||
|
ScheduledDate = dispatch.ScheduledDate,
|
||||||
|
CompletedDate = dispatch.CompletedDate,
|
||||||
|
CreatedDate = dispatch.CreatedDate,
|
||||||
|
CreatedBy = dispatch.createdby
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
149
SeaHaven.Services/Implementation/EmployeeService.cs
Normal file
149
SeaHaven.Services/Implementation/EmployeeService.cs
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
using Data.SeaHavenIndustries;
|
||||||
|
using SeaHaven.DataServices.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace SeaHaven.Services.Implementation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Employee service implementation
|
||||||
|
/// Contains business logic, validation, and orchestration for Employee operations
|
||||||
|
/// </summary>
|
||||||
|
public class EmployeeService : IEmployeeService
|
||||||
|
{
|
||||||
|
private readonly IEmployeeDataService _employeeDataService;
|
||||||
|
|
||||||
|
public EmployeeService(IEmployeeDataService employeeDataService)
|
||||||
|
{
|
||||||
|
_employeeDataService = employeeDataService;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query operations
|
||||||
|
public async Task<EmployeeDTO?> GetEmployeeByIdAsync(int id)
|
||||||
|
{
|
||||||
|
var employee = await _employeeDataService.GetByIdAsync(id);
|
||||||
|
return employee == null ? null : MapToDTO(employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<EmployeeDTO?> GetEmployeeByIdWithDetailsAsync(int id)
|
||||||
|
{
|
||||||
|
var employee = await _employeeDataService.GetByIdWithDetailsAsync(id);
|
||||||
|
return employee == null ? null : MapToDTO(employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<EmployeeDTO>> GetAllEmployeesAsync()
|
||||||
|
{
|
||||||
|
var employees = await _employeeDataService.GetAllAsync();
|
||||||
|
return employees.Select(MapToDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PagedResult<EmployeeDTO>> GetEmployeesPagedAsync(int page, int pageSize, string? search = null)
|
||||||
|
{
|
||||||
|
var (items, totalCount) = await _employeeDataService.GetPagedAsync(page, pageSize, search);
|
||||||
|
return new PagedResult<EmployeeDTO>
|
||||||
|
{
|
||||||
|
Items = items.Select(MapToDTO).ToList(),
|
||||||
|
TotalCount = totalCount,
|
||||||
|
Page = page,
|
||||||
|
PageSize = pageSize
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<EmployeeDTO> CreateEmployeeAsync(CreateEmployeeDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var employee = new Employee
|
||||||
|
{
|
||||||
|
FirstName = dto.FirstName,
|
||||||
|
LastName = dto.LastName,
|
||||||
|
DepartmentId = dto.DepartmentId,
|
||||||
|
JobTitleId = dto.JobTitleId,
|
||||||
|
RegionId = dto.RegionId,
|
||||||
|
CreatedDate = DateTime.UtcNow,
|
||||||
|
CreatedBy = userId
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(dto.Email))
|
||||||
|
{
|
||||||
|
employee.Emails.Add(new EmployeeEmail
|
||||||
|
{
|
||||||
|
Address = dto.Email,
|
||||||
|
IsPrimary = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(dto.Phone))
|
||||||
|
{
|
||||||
|
employee.Phones.Add(new EmployeePhone
|
||||||
|
{
|
||||||
|
Number = dto.Phone,
|
||||||
|
IsPrimary = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var created = await _employeeDataService.AddAsync(employee);
|
||||||
|
return MapToDTO(created);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<EmployeeDTO> UpdateEmployeeAsync(int id, UpdateEmployeeDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var employee = await _employeeDataService.GetByIdAsync(id);
|
||||||
|
if (employee == null)
|
||||||
|
throw new InvalidOperationException($"Employee with ID {id} not found");
|
||||||
|
|
||||||
|
if (dto.FirstName != null) employee.FirstName = dto.FirstName;
|
||||||
|
if (dto.LastName != null) employee.LastName = dto.LastName;
|
||||||
|
if (dto.DepartmentId.HasValue) employee.DepartmentId = dto.DepartmentId;
|
||||||
|
if (dto.JobTitleId.HasValue) employee.JobTitleId = dto.JobTitleId;
|
||||||
|
if (dto.RegionId.HasValue) employee.RegionId = dto.RegionId;
|
||||||
|
|
||||||
|
employee.LastModificationTime = DateTime.UtcNow;
|
||||||
|
employee.LastModifierUserId = int.Parse(userId);
|
||||||
|
|
||||||
|
await _employeeDataService.UpdateAsync(employee);
|
||||||
|
return MapToDTO(employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteEmployeeAsync(int id, string userId)
|
||||||
|
{
|
||||||
|
var employee = await _employeeDataService.GetByIdAsync(id);
|
||||||
|
if (employee == null)
|
||||||
|
throw new InvalidOperationException($"Employee with ID {id} not found");
|
||||||
|
|
||||||
|
employee.IsDeleted = true;
|
||||||
|
employee.CreatedBy = userId;
|
||||||
|
employee.LastModificationTime = DateTime.UtcNow;
|
||||||
|
|
||||||
|
await _employeeDataService.UpdateAsync(employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> EmployeeExistsAsync(int id)
|
||||||
|
{
|
||||||
|
return await _employeeDataService.ExistsAsync(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetTotalEmployeeCountAsync()
|
||||||
|
{
|
||||||
|
return await _employeeDataService.CountAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private helper methods
|
||||||
|
private EmployeeDTO MapToDTO(Employee employee)
|
||||||
|
{
|
||||||
|
return new EmployeeDTO
|
||||||
|
{
|
||||||
|
Id = employee.Id,
|
||||||
|
FirstName = employee.FirstName,
|
||||||
|
LastName = employee.LastName,
|
||||||
|
Email = employee.Emails?.FirstOrDefault(e => e.IsPrimary == true)?.Address,
|
||||||
|
Phone = employee.Phones?.FirstOrDefault(p => p.IsPrimary == true)?.Number,
|
||||||
|
DepartmentId = employee.DepartmentId,
|
||||||
|
DepartmentName = employee.Department?.Name,
|
||||||
|
JobTitleId = employee.JobTitleId,
|
||||||
|
JobTitleName = employee.JobTitle?.Name,
|
||||||
|
RegionId = employee.RegionId,
|
||||||
|
RegionName = employee.Region?.Name,
|
||||||
|
CreatedDate = employee.CreatedDate
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
150
SeaHaven.Services/Implementation/FollowUpService.cs
Normal file
150
SeaHaven.Services/Implementation/FollowUpService.cs
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
using Data.SeaHavenIndustries;
|
||||||
|
using SeaHaven.DataServices.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace SeaHaven.Services.Implementation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Follow-Up service implementation
|
||||||
|
/// Contains business logic, validation, and orchestration for Follow-Up operations
|
||||||
|
/// </summary>
|
||||||
|
public class FollowUpService : IFollowUpService
|
||||||
|
{
|
||||||
|
private readonly IFollowUpDataService _followUpDataService;
|
||||||
|
|
||||||
|
public FollowUpService(IFollowUpDataService followUpDataService)
|
||||||
|
{
|
||||||
|
_followUpDataService = followUpDataService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<FollowUpDTO?> GetFollowUpByIdAsync(int id)
|
||||||
|
{
|
||||||
|
var followUp = await _followUpDataService.GetByIdAsync(id);
|
||||||
|
return followUp == null ? null : MapToDTO(followUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<FollowUpDTO?> GetFollowUpByIdWithDetailsAsync(int id)
|
||||||
|
{
|
||||||
|
var followUp = await _followUpDataService.GetByIdWithDetailsAsync(id);
|
||||||
|
return followUp == null ? null : MapToDTO(followUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<FollowUpDTO>> GetAllFollowUpsAsync()
|
||||||
|
{
|
||||||
|
var followUps = await _followUpDataService.GetAllAsync();
|
||||||
|
return followUps.Select(MapToDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<FollowUpDTO>> GetFollowUpsByWorkOrderIdAsync(int workOrderId)
|
||||||
|
{
|
||||||
|
var followUps = await _followUpDataService.GetByWorkOrderIdAsync(workOrderId);
|
||||||
|
return followUps.Select(MapToDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PagedResult<FollowUpDTO>> GetFollowUpsPagedAsync(int page, int pageSize, string? search = null, string? status = null)
|
||||||
|
{
|
||||||
|
var (items, totalCount) = await _followUpDataService.GetPagedAsync(page, pageSize, search);
|
||||||
|
|
||||||
|
var filteredItems = items.AsEnumerable();
|
||||||
|
if (!string.IsNullOrWhiteSpace(status))
|
||||||
|
{
|
||||||
|
filteredItems = filteredItems.Where(f => f.Status == status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PagedResult<FollowUpDTO>
|
||||||
|
{
|
||||||
|
Items = filteredItems.Select(MapToDTO).ToList(),
|
||||||
|
TotalCount = totalCount,
|
||||||
|
Page = page,
|
||||||
|
PageSize = pageSize
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<FollowUpDTO> CreateFollowUpAsync(CreateFollowUpDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var followUp = new FollowUps
|
||||||
|
{
|
||||||
|
Reason = dto.Reason,
|
||||||
|
ScheduleDate = dto.ScheduleDate,
|
||||||
|
ScheduleStartTime = dto.ScheduleStartTime,
|
||||||
|
Status = dto.Status,
|
||||||
|
EmployeeId = dto.EmployeeId,
|
||||||
|
WorkOrderId = dto.WorkOrderId,
|
||||||
|
AccountId = dto.AccountId,
|
||||||
|
LocationId = dto.LocationId,
|
||||||
|
CreatedDate = DateTime.UtcNow,
|
||||||
|
createdby = userId
|
||||||
|
};
|
||||||
|
|
||||||
|
var created = await _followUpDataService.AddAsync(followUp);
|
||||||
|
return MapToDTO(created);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<FollowUpDTO> UpdateFollowUpAsync(int id, UpdateFollowUpDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var followUp = await _followUpDataService.GetByIdAsync(id);
|
||||||
|
if (followUp == null)
|
||||||
|
throw new InvalidOperationException($"Follow-Up with ID {id} not found");
|
||||||
|
|
||||||
|
if (dto.Reason != null) followUp.Reason = dto.Reason;
|
||||||
|
if (dto.ScheduleDate.HasValue) followUp.ScheduleDate = dto.ScheduleDate.Value;
|
||||||
|
if (dto.ScheduleStartTime.HasValue) followUp.ScheduleStartTime = dto.ScheduleStartTime.Value;
|
||||||
|
if (dto.Status != null) followUp.Status = dto.Status;
|
||||||
|
if (dto.EmployeeId.HasValue) followUp.EmployeeId = dto.EmployeeId;
|
||||||
|
if (dto.WorkOrderId.HasValue) followUp.WorkOrderId = dto.WorkOrderId;
|
||||||
|
if (dto.AccountId.HasValue) followUp.AccountId = dto.AccountId;
|
||||||
|
if (dto.LocationId.HasValue) followUp.LocationId = dto.LocationId;
|
||||||
|
|
||||||
|
followUp.LastModificationTime = DateTime.UtcNow;
|
||||||
|
if (int.TryParse(userId, out int userIdInt))
|
||||||
|
followUp.LastModifierUserId = userIdInt;
|
||||||
|
|
||||||
|
await _followUpDataService.UpdateAsync(followUp);
|
||||||
|
return MapToDTO(followUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteFollowUpAsync(int id, string userId)
|
||||||
|
{
|
||||||
|
var followUp = await _followUpDataService.GetByIdAsync(id);
|
||||||
|
if (followUp == null)
|
||||||
|
throw new InvalidOperationException($"Follow-Up with ID {id} not found");
|
||||||
|
|
||||||
|
followUp.IsDeleted = true;
|
||||||
|
followUp.DeleterUserId = userId;
|
||||||
|
followUp.DeletionTime = DateTime.UtcNow;
|
||||||
|
|
||||||
|
await _followUpDataService.UpdateAsync(followUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> FollowUpExistsAsync(int id)
|
||||||
|
{
|
||||||
|
return await _followUpDataService.ExistsAsync(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetTotalFollowUpCountAsync()
|
||||||
|
{
|
||||||
|
return await _followUpDataService.CountAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private FollowUpDTO MapToDTO(FollowUps followUp)
|
||||||
|
{
|
||||||
|
return new FollowUpDTO
|
||||||
|
{
|
||||||
|
Id = followUp.Id,
|
||||||
|
Reason = followUp.Reason,
|
||||||
|
ScheduleDate = followUp.ScheduleDate,
|
||||||
|
ScheduleStartTime = followUp.ScheduleStartTime,
|
||||||
|
Status = followUp.Status,
|
||||||
|
EmployeeId = followUp.EmployeeId,
|
||||||
|
EmployeeName = followUp.Employee != null ? $"{followUp.Employee.FirstName} {followUp.Employee.LastName}" : null,
|
||||||
|
WorkOrderId = followUp.WorkOrderId,
|
||||||
|
AccountId = followUp.AccountId,
|
||||||
|
AccountName = followUp.Account?.Name,
|
||||||
|
LocationId = followUp.LocationId,
|
||||||
|
LocationName = followUp.Location?.Name,
|
||||||
|
CreatedDate = followUp.CreatedDate
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
142
SeaHaven.Services/Implementation/LocationService.cs
Normal file
142
SeaHaven.Services/Implementation/LocationService.cs
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
using Data.SeaHavenIndustries;
|
||||||
|
using SeaHaven.DataServices.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace SeaHaven.Services.Implementation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Location service implementation
|
||||||
|
/// Contains business logic, validation, and orchestration for Location operations
|
||||||
|
/// </summary>
|
||||||
|
public class LocationService : ILocationService
|
||||||
|
{
|
||||||
|
private readonly ILocationDataService _locationDataService;
|
||||||
|
|
||||||
|
public LocationService(ILocationDataService locationDataService)
|
||||||
|
{
|
||||||
|
_locationDataService = locationDataService;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query operations
|
||||||
|
public async Task<LocationDTO?> GetLocationByIdAsync(int id)
|
||||||
|
{
|
||||||
|
var location = await _locationDataService.GetByIdAsync(id);
|
||||||
|
return location == null ? null : MapToDTO(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LocationDTO?> GetLocationByIdWithDetailsAsync(int id)
|
||||||
|
{
|
||||||
|
var location = await _locationDataService.GetByIdWithDetailsAsync(id);
|
||||||
|
return location == null ? null : MapToDTO(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<LocationDTO>> GetAllLocationsAsync()
|
||||||
|
{
|
||||||
|
var locations = await _locationDataService.GetAllAsync();
|
||||||
|
return locations.Select(MapToDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<LocationDTO>> GetLocationsByAccountIdAsync(int accountId)
|
||||||
|
{
|
||||||
|
var locations = await _locationDataService.GetByAccountIdAsync(accountId);
|
||||||
|
return locations.Select(MapToDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PagedResult<LocationDTO>> GetLocationsPagedAsync(int page, int pageSize, string? search = null)
|
||||||
|
{
|
||||||
|
var (items, totalCount) = await _locationDataService.GetPagedAsync(page, pageSize, search);
|
||||||
|
return new PagedResult<LocationDTO>
|
||||||
|
{
|
||||||
|
Items = items.Select(MapToDTO).ToList(),
|
||||||
|
TotalCount = totalCount,
|
||||||
|
Page = page,
|
||||||
|
PageSize = pageSize
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LocationDTO> CreateLocationAsync(CreateLocationDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var location = new Locations
|
||||||
|
{
|
||||||
|
Name = dto.LocationName,
|
||||||
|
Title = dto.LocationName,
|
||||||
|
Address1 = dto.Address,
|
||||||
|
City = dto.City,
|
||||||
|
State = dto.State,
|
||||||
|
Zip = dto.Zipcode,
|
||||||
|
CreatedDate = DateTime.UtcNow,
|
||||||
|
createdby = userId
|
||||||
|
};
|
||||||
|
|
||||||
|
var created = await _locationDataService.AddAsync(location);
|
||||||
|
return MapToDTO(created);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LocationDTO> UpdateLocationAsync(int id, UpdateLocationDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var location = await _locationDataService.GetByIdAsync(id);
|
||||||
|
if (location == null)
|
||||||
|
throw new InvalidOperationException($"Location with ID {id} not found");
|
||||||
|
|
||||||
|
// Update properties
|
||||||
|
if (dto.LocationName != null) location.Name = dto.LocationName;
|
||||||
|
if (dto.LocationName != null) location.Title = dto.LocationName;
|
||||||
|
if (dto.Address != null) location.Address1 = dto.Address;
|
||||||
|
if (dto.City != null) location.City = dto.City;
|
||||||
|
if (dto.State != null) location.State = dto.State;
|
||||||
|
if (dto.Zipcode != null) location.Zip = dto.Zipcode;
|
||||||
|
|
||||||
|
location.LastModificationTime = DateTime.UtcNow;
|
||||||
|
if (int.TryParse(userId, out int userIdInt))
|
||||||
|
location.LastModifierUserId = userIdInt;
|
||||||
|
|
||||||
|
await _locationDataService.UpdateAsync(location);
|
||||||
|
return MapToDTO(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteLocationAsync(int id, string userId)
|
||||||
|
{
|
||||||
|
var location = await _locationDataService.GetByIdAsync(id);
|
||||||
|
if (location == null)
|
||||||
|
throw new InvalidOperationException($"Location with ID {id} not found");
|
||||||
|
|
||||||
|
location.IsDeleted = true;
|
||||||
|
location.DeleterUserId = userId;
|
||||||
|
location.DeletionTime = DateTime.UtcNow;
|
||||||
|
|
||||||
|
await _locationDataService.UpdateAsync(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> LocationExistsAsync(int id)
|
||||||
|
{
|
||||||
|
return await _locationDataService.ExistsAsync(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetTotalLocationCountAsync()
|
||||||
|
{
|
||||||
|
return await _locationDataService.CountAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private helper methods
|
||||||
|
private LocationDTO MapToDTO(Locations location)
|
||||||
|
{
|
||||||
|
return new LocationDTO
|
||||||
|
{
|
||||||
|
Id = location.Id,
|
||||||
|
Name = location.Name,
|
||||||
|
Title = location.Title,
|
||||||
|
Address1 = location.Address1,
|
||||||
|
Address2 = location.Address2,
|
||||||
|
City = location.City,
|
||||||
|
State = location.State,
|
||||||
|
Zip = location.Zip,
|
||||||
|
PhoneNumber = location.PhoneNumber,
|
||||||
|
Email = location.Email,
|
||||||
|
Status = location.Status,
|
||||||
|
CreatedDate = location.CreatedDate,
|
||||||
|
CreatedBy = location.createdby
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
136
SeaHaven.Services/Implementation/PMScheduleService.cs
Normal file
136
SeaHaven.Services/Implementation/PMScheduleService.cs
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
using Data.SeaHavenIndustries;
|
||||||
|
using SeaHaven.DataServices.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace SeaHaven.Services.Implementation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// PM Schedule service implementation
|
||||||
|
/// Contains business logic, validation, and orchestration for PM Schedule operations
|
||||||
|
/// </summary>
|
||||||
|
public class PMScheduleService : IPMScheduleService
|
||||||
|
{
|
||||||
|
private readonly IPMScheduleDataService _pmScheduleDataService;
|
||||||
|
|
||||||
|
public PMScheduleService(IPMScheduleDataService pmScheduleDataService)
|
||||||
|
{
|
||||||
|
_pmScheduleDataService = pmScheduleDataService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PMScheduleDTO?> GetPMScheduleByIdAsync(int id)
|
||||||
|
{
|
||||||
|
var pmSchedule = await _pmScheduleDataService.GetByIdAsync(id);
|
||||||
|
return pmSchedule == null ? null : MapToDTO(pmSchedule);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PMScheduleDTO?> GetPMScheduleByIdWithDetailsAsync(int id)
|
||||||
|
{
|
||||||
|
var pmSchedule = await _pmScheduleDataService.GetByIdWithDetailsAsync(id);
|
||||||
|
return pmSchedule == null ? null : MapToDTO(pmSchedule);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<PMScheduleDTO>> GetAllPMSchedulesAsync()
|
||||||
|
{
|
||||||
|
var pmSchedules = await _pmScheduleDataService.GetAllWithDetailsAsync();
|
||||||
|
return pmSchedules.Select(MapToDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<PMScheduleDTO>> GetPMSchedulesByLocationIdAsync(int locationId)
|
||||||
|
{
|
||||||
|
var pmSchedules = await _pmScheduleDataService.GetAllWithDetailsAsync();
|
||||||
|
return pmSchedules.Where(p => p.LocationId == locationId).Select(MapToDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PagedResult<PMScheduleDTO>> GetPMSchedulesPagedAsync(int page, int pageSize, string? search = null)
|
||||||
|
{
|
||||||
|
var (items, totalCount) = await _pmScheduleDataService.GetPagedAsync(page, pageSize, search);
|
||||||
|
return new PagedResult<PMScheduleDTO>
|
||||||
|
{
|
||||||
|
Items = items.Select(MapToDTO).ToList(),
|
||||||
|
TotalCount = totalCount,
|
||||||
|
Page = page,
|
||||||
|
PageSize = pageSize
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PMScheduleDTO> CreatePMScheduleAsync(CreatePMScheduleDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var pmSchedule = new PMSchedules
|
||||||
|
{
|
||||||
|
Name = dto.Name,
|
||||||
|
Frequency = dto.Frequency,
|
||||||
|
StartDate = dto.StartDate,
|
||||||
|
IsActive = dto.IsActive,
|
||||||
|
AssetId = dto.AssetId,
|
||||||
|
LocationId = dto.LocationId,
|
||||||
|
CreatedDate = DateTime.UtcNow,
|
||||||
|
createdby = userId
|
||||||
|
};
|
||||||
|
|
||||||
|
var created = await _pmScheduleDataService.AddAsync(pmSchedule);
|
||||||
|
return MapToDTO(created);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PMScheduleDTO> UpdatePMScheduleAsync(int id, UpdatePMScheduleDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var pmSchedule = await _pmScheduleDataService.GetByIdAsync(id);
|
||||||
|
if (pmSchedule == null)
|
||||||
|
throw new InvalidOperationException($"PM Schedule with ID {id} not found");
|
||||||
|
|
||||||
|
if (dto.Name != null) pmSchedule.Name = dto.Name;
|
||||||
|
if (dto.Frequency != null) pmSchedule.Frequency = dto.Frequency;
|
||||||
|
if (dto.StartDate.HasValue) pmSchedule.StartDate = dto.StartDate.Value;
|
||||||
|
if (dto.IsActive.HasValue) pmSchedule.IsActive = dto.IsActive.Value;
|
||||||
|
if (dto.AssetId.HasValue) pmSchedule.AssetId = dto.AssetId;
|
||||||
|
if (dto.LocationId.HasValue) pmSchedule.LocationId = dto.LocationId;
|
||||||
|
|
||||||
|
pmSchedule.LastModificationTime = DateTime.UtcNow;
|
||||||
|
if (int.TryParse(userId, out int userIdInt))
|
||||||
|
pmSchedule.LastModifierUserId = userIdInt;
|
||||||
|
|
||||||
|
await _pmScheduleDataService.UpdateAsync(pmSchedule);
|
||||||
|
return MapToDTO(pmSchedule);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeletePMScheduleAsync(int id, string userId)
|
||||||
|
{
|
||||||
|
var pmSchedule = await _pmScheduleDataService.GetByIdAsync(id);
|
||||||
|
if (pmSchedule == null)
|
||||||
|
throw new InvalidOperationException($"PM Schedule with ID {id} not found");
|
||||||
|
|
||||||
|
pmSchedule.IsDeleted = true;
|
||||||
|
pmSchedule.DeleterUserId = userId;
|
||||||
|
pmSchedule.DeletionTime = DateTime.UtcNow;
|
||||||
|
|
||||||
|
await _pmScheduleDataService.UpdateAsync(pmSchedule);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> PMScheduleExistsAsync(int id)
|
||||||
|
{
|
||||||
|
return await _pmScheduleDataService.ExistsAsync(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetTotalPMScheduleCountAsync()
|
||||||
|
{
|
||||||
|
return await _pmScheduleDataService.CountAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private PMScheduleDTO MapToDTO(PMSchedules pmSchedule)
|
||||||
|
{
|
||||||
|
return new PMScheduleDTO
|
||||||
|
{
|
||||||
|
Id = pmSchedule.Id,
|
||||||
|
Name = pmSchedule.Name,
|
||||||
|
Frequency = pmSchedule.Frequency,
|
||||||
|
StartDate = pmSchedule.StartDate,
|
||||||
|
IsActive = pmSchedule.IsActive,
|
||||||
|
AssetId = pmSchedule.AssetId,
|
||||||
|
AssetName = pmSchedule.Asset?.Name,
|
||||||
|
LocationId = pmSchedule.LocationId,
|
||||||
|
LocationName = pmSchedule.Location?.Name,
|
||||||
|
CreatedDate = pmSchedule.CreatedDate
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
130
SeaHaven.Services/Implementation/VendorService.cs
Normal file
130
SeaHaven.Services/Implementation/VendorService.cs
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
using Data.SeaHavenIndustries;
|
||||||
|
using SeaHaven.DataServices.Interfaces;
|
||||||
|
using SeaHaven.Services.DTOs;
|
||||||
|
using SeaHaven.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace SeaHaven.Services.Implementation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Vendor service implementation
|
||||||
|
/// Contains business logic, validation, and orchestration for Vendor operations
|
||||||
|
/// </summary>
|
||||||
|
public class VendorService : IVendorService
|
||||||
|
{
|
||||||
|
private readonly IVendorDataService _vendorDataService;
|
||||||
|
|
||||||
|
public VendorService(IVendorDataService vendorDataService)
|
||||||
|
{
|
||||||
|
_vendorDataService = vendorDataService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<VendorDTO?> GetVendorByIdAsync(int id)
|
||||||
|
{
|
||||||
|
var vendor = await _vendorDataService.GetByIdAsync(id);
|
||||||
|
return vendor == null ? null : MapToDTO(vendor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<VendorDTO?> GetVendorByIdWithDetailsAsync(int id)
|
||||||
|
{
|
||||||
|
var vendor = await _vendorDataService.GetByIdWithDetailsAsync(id);
|
||||||
|
return vendor == null ? null : MapToDTO(vendor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<VendorDTO>> GetAllVendorsAsync()
|
||||||
|
{
|
||||||
|
var vendors = await _vendorDataService.GetAllAsync();
|
||||||
|
return vendors.Select(MapToDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PagedResult<VendorDTO>> GetVendorsPagedAsync(int page, int pageSize, string? search = null)
|
||||||
|
{
|
||||||
|
var (items, totalCount) = await _vendorDataService.GetPagedAsync(page, pageSize, search);
|
||||||
|
return new PagedResult<VendorDTO>
|
||||||
|
{
|
||||||
|
Items = items.Select(MapToDTO).ToList(),
|
||||||
|
TotalCount = totalCount,
|
||||||
|
Page = page,
|
||||||
|
PageSize = pageSize
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<VendorDTO> CreateVendorAsync(CreateVendorDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var vendor = new Vendor
|
||||||
|
{
|
||||||
|
CompanyName = dto.Name,
|
||||||
|
Email = dto.Email,
|
||||||
|
Phone = dto.Phone,
|
||||||
|
Address = dto.Address,
|
||||||
|
City = dto.City,
|
||||||
|
State = dto.State,
|
||||||
|
Zip = dto.Zipcode,
|
||||||
|
CreatedDate = DateTime.UtcNow,
|
||||||
|
createdby = userId
|
||||||
|
};
|
||||||
|
|
||||||
|
var created = await _vendorDataService.AddAsync(vendor);
|
||||||
|
return MapToDTO(created);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<VendorDTO> UpdateVendorAsync(int id, UpdateVendorDTO dto, string userId)
|
||||||
|
{
|
||||||
|
var vendor = await _vendorDataService.GetByIdAsync(id);
|
||||||
|
if (vendor == null)
|
||||||
|
throw new InvalidOperationException($"Vendor with ID {id} not found");
|
||||||
|
|
||||||
|
if (dto.Name != null) vendor.CompanyName = dto.Name;
|
||||||
|
if (dto.Email != null) vendor.Email = dto.Email;
|
||||||
|
if (dto.Phone != null) vendor.Phone = dto.Phone;
|
||||||
|
if (dto.Address != null) vendor.Address = dto.Address;
|
||||||
|
if (dto.City != null) vendor.City = dto.City;
|
||||||
|
if (dto.State != null) vendor.State = dto.State;
|
||||||
|
if (dto.Zipcode != null) vendor.Zip = dto.Zipcode;
|
||||||
|
|
||||||
|
vendor.LastModificationTime = DateTime.UtcNow;
|
||||||
|
if (int.TryParse(userId, out int userIdInt))
|
||||||
|
vendor.LastModifierUserId = userIdInt;
|
||||||
|
|
||||||
|
await _vendorDataService.UpdateAsync(vendor);
|
||||||
|
return MapToDTO(vendor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteVendorAsync(int id, string userId)
|
||||||
|
{
|
||||||
|
var vendor = await _vendorDataService.GetByIdAsync(id);
|
||||||
|
if (vendor == null)
|
||||||
|
throw new InvalidOperationException($"Vendor with ID {id} not found");
|
||||||
|
|
||||||
|
vendor.IsDeleted = true;
|
||||||
|
vendor.DeleterUserId = userId;
|
||||||
|
vendor.DeletionTime = DateTime.UtcNow;
|
||||||
|
|
||||||
|
await _vendorDataService.UpdateAsync(vendor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> VendorExistsAsync(int id)
|
||||||
|
{
|
||||||
|
return await _vendorDataService.ExistsAsync(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetTotalVendorCountAsync()
|
||||||
|
{
|
||||||
|
return await _vendorDataService.CountAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private VendorDTO MapToDTO(Vendor vendor)
|
||||||
|
{
|
||||||
|
return new VendorDTO
|
||||||
|
{
|
||||||
|
Id = vendor.Id,
|
||||||
|
Name = vendor.CompanyName,
|
||||||
|
Email = vendor.Email,
|
||||||
|
Phone = vendor.Phone,
|
||||||
|
Address = vendor.Address,
|
||||||
|
City = vendor.City,
|
||||||
|
State = vendor.State,
|
||||||
|
Zipcode = vendor.Zip
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue