mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 17:43:12 +00:00
231 lines
8.3 KiB
C#
231 lines
8.3 KiB
C#
using Data.SeaHavenIndustries;
|
|
using FluentValidation;
|
|
using SeaHaven.DataServices.Interfaces;
|
|
using SeaHaven.Services.DTOs;
|
|
using SeaHaven.Services.Interfaces;
|
|
using SeaHaven.Services.Validation;
|
|
|
|
namespace SeaHaven.Services.Implementation
|
|
{
|
|
/// <summary>
|
|
/// Contact service implementation
|
|
/// Contains business logic, validation, and orchestration for Contact operations
|
|
/// </summary>
|
|
public class ContactService : IContactService
|
|
{
|
|
private readonly IContactDataService _contactDataService;
|
|
private readonly ICreateContactValidation _createValidator;
|
|
private readonly IUpdateContactValidation _updateValidator;
|
|
|
|
public ContactService(
|
|
IContactDataService contactDataService,
|
|
ICreateContactValidation createValidator,
|
|
IUpdateContactValidation updateValidator)
|
|
{
|
|
_contactDataService = contactDataService;
|
|
_createValidator = createValidator;
|
|
_updateValidator = updateValidator;
|
|
}
|
|
|
|
// Query operations
|
|
public async Task<ContactDTO?> GetContactByIdAsync(int id)
|
|
{
|
|
var contact = await _contactDataService.GetByIdAsync(id);
|
|
return contact == null ? null : MapToDTO(contact);
|
|
}
|
|
|
|
public async Task<ContactDTO?> GetContactByIdWithDetailsAsync(int id)
|
|
{
|
|
var contact = await _contactDataService.GetByIdWithDetailsAsync(id);
|
|
return contact == null ? null : MapToDTO(contact);
|
|
}
|
|
|
|
public async Task<IEnumerable<ContactDTO>> GetAllContactsAsync()
|
|
{
|
|
var contacts = await _contactDataService.GetAllAsync();
|
|
return contacts.Select(MapToDTO);
|
|
}
|
|
|
|
public async Task<IEnumerable<ContactDTO>> GetContactsByAccountIdAsync(int accountId)
|
|
{
|
|
var contacts = await _contactDataService.GetByAccountIdAsync(accountId);
|
|
return contacts.Select(MapToDTO);
|
|
}
|
|
|
|
public async Task<IEnumerable<ContactDTO>> GetContactsByTypeAsync(string type)
|
|
{
|
|
var contacts = await _contactDataService.GetByTypeAsync(type);
|
|
return contacts.Select(MapToDTO);
|
|
}
|
|
|
|
public async Task<ContactDTO?> GetContactByEmailAsync(string email)
|
|
{
|
|
var contact = await _contactDataService.GetByEmailAsync(email);
|
|
return contact == null ? null : MapToDTO(contact);
|
|
}
|
|
|
|
// Paged results
|
|
public async Task<PagedResult<ContactDTO>> GetContactsPagedAsync(
|
|
int page,
|
|
int pageSize,
|
|
string? search = null,
|
|
string? type = null)
|
|
{
|
|
var (items, totalCount) = await _contactDataService.GetPagedAsync(page, pageSize, search, type);
|
|
|
|
return new PagedResult<ContactDTO>
|
|
{
|
|
Items = items.Select(MapToDTO),
|
|
TotalCount = totalCount,
|
|
Page = page,
|
|
PageSize = pageSize
|
|
};
|
|
}
|
|
|
|
// Command operations
|
|
public async Task<ContactDTO> CreateContactAsync(CreateContactDTO dto, string userId)
|
|
{
|
|
var validationResult = await _createValidator.ValidateAsync(dto);
|
|
if (!validationResult.IsValid)
|
|
{
|
|
throw new ValidationException(validationResult.Errors);
|
|
}
|
|
|
|
if (await _contactDataService.EmailExistsAsync(dto.Email))
|
|
throw new InvalidOperationException($"Email '{dto.Email}' already exists");
|
|
|
|
var contact = new Contacts
|
|
{
|
|
FirstName = dto.FirstName,
|
|
LastName = dto.LastName,
|
|
Email = dto.Email,
|
|
PhoneNumber = dto.Phone ?? dto.Mobile,
|
|
Title = dto.Title,
|
|
ContactType = dto.Type,
|
|
AccountId = dto.AccountId,
|
|
createdby = userId,
|
|
CreatedDate = DateTime.Now
|
|
};
|
|
|
|
var savedContact = await _contactDataService.AddAsync(contact);
|
|
|
|
return MapToDTO(savedContact);
|
|
}
|
|
|
|
public async Task<ContactDTO> UpdateContactAsync(int id, UpdateContactDTO dto, string userId)
|
|
{
|
|
var validationResult = await _updateValidator.ValidateAsync(dto);
|
|
if (!validationResult.IsValid)
|
|
{
|
|
throw new ValidationException(validationResult.Errors);
|
|
}
|
|
|
|
var existingContact = await _contactDataService.GetByIdAsync(id);
|
|
if (existingContact == null)
|
|
throw new KeyNotFoundException($"Contact with ID {id} not found");
|
|
|
|
if (!string.IsNullOrWhiteSpace(dto.Email) && dto.Email != existingContact.Email)
|
|
{
|
|
if (await _contactDataService.EmailExistsAsync(dto.Email, id))
|
|
throw new InvalidOperationException($"Email '{dto.Email}' already exists");
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(dto.FirstName))
|
|
existingContact.FirstName = dto.FirstName;
|
|
|
|
if (!string.IsNullOrWhiteSpace(dto.LastName))
|
|
existingContact.LastName = dto.LastName;
|
|
|
|
if (!string.IsNullOrWhiteSpace(dto.Email))
|
|
existingContact.Email = dto.Email;
|
|
|
|
if (dto.Phone != null || dto.Mobile != null)
|
|
existingContact.PhoneNumber = dto.Phone ?? dto.Mobile;
|
|
|
|
if (dto.Title != null)
|
|
existingContact.Title = dto.Title;
|
|
|
|
if (dto.Type != null)
|
|
existingContact.ContactType = dto.Type;
|
|
|
|
if (dto.AccountId.HasValue)
|
|
existingContact.AccountId = dto.AccountId;
|
|
|
|
existingContact.LastModificationTime = DateTime.Now;
|
|
|
|
await _contactDataService.UpdateAsync(existingContact);
|
|
|
|
return MapToDTO(existingContact);
|
|
}
|
|
|
|
public async Task DeleteContactAsync(int id, string userId)
|
|
{
|
|
// Check if exists
|
|
if (!await _contactDataService.ExistsAsync(id))
|
|
throw new KeyNotFoundException($"Contact with ID {id} not found");
|
|
|
|
// Business logic: Check if contact is being used (add your logic here)
|
|
// For example, check if contact is linked to work orders, etc.
|
|
|
|
await _contactDataService.DeleteAsync(id);
|
|
}
|
|
|
|
// Validation operations
|
|
public async Task<bool> ContactExistsAsync(int id)
|
|
{
|
|
return await _contactDataService.ExistsAsync(id);
|
|
}
|
|
|
|
public async Task<bool> EmailExistsAsync(string email, int? excludeId = null)
|
|
{
|
|
return await _contactDataService.EmailExistsAsync(email, excludeId);
|
|
}
|
|
|
|
public async Task<bool> PhoneExistsAsync(string phone, int? excludeId = null)
|
|
{
|
|
return await _contactDataService.PhoneExistsAsync(phone, excludeId);
|
|
}
|
|
|
|
// Statistics
|
|
public async Task<int> GetTotalContactCountAsync()
|
|
{
|
|
return await _contactDataService.CountAsync();
|
|
}
|
|
|
|
public async Task<int> GetContactCountByAccountAsync(int accountId)
|
|
{
|
|
return await _contactDataService.CountByAccountIdAsync(accountId);
|
|
}
|
|
|
|
public async Task<Dictionary<string, int>> GetContactCountByTypeAsync()
|
|
{
|
|
var contacts = await _contactDataService.GetAllAsync();
|
|
return contacts
|
|
.Where(c => !string.IsNullOrWhiteSpace(c.ContactType))
|
|
.GroupBy(c => c.ContactType!)
|
|
.ToDictionary(g => g.Key, g => g.Count());
|
|
}
|
|
|
|
// Private mapping methods
|
|
private static ContactDTO MapToDTO(Contacts contact)
|
|
{
|
|
return new ContactDTO
|
|
{
|
|
Id = contact.Id,
|
|
FirstName = contact.FirstName,
|
|
LastName = contact.LastName,
|
|
Email = contact.Email,
|
|
Phone = contact.PhoneNumber,
|
|
Mobile = contact.PhoneNumber, // Contacts only has one PhoneNumber field
|
|
Title = contact.Title,
|
|
Type = contact.ContactType,
|
|
AccountId = contact.AccountId,
|
|
AccountName = contact.Account?.Name,
|
|
CreatedDate = contact.CreatedDate,
|
|
CreatedBy = contact.createdby,
|
|
ModifiedDate = contact.LastModificationTime,
|
|
ModifiedBy = null // Not tracked in FullAuditEntity
|
|
};
|
|
}
|
|
}
|
|
}
|