Files
meezi/src/Meezi.API/Services/CustomerService.cs
T

137 lines
5.0 KiB
C#
Raw Normal View History

2026-05-27 21:33:48 +03:30
using Meezi.API.Models.Crm;
using Meezi.Core.Entities;
using Meezi.Core.Utilities;
using Meezi.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
namespace Meezi.API.Services;
public interface ICustomerService
{
Task<IReadOnlyList<CustomerDto>> SearchAsync(string cafeId, string? query, CancellationToken cancellationToken = default);
Task<CustomerDto?> GetAsync(string cafeId, string id, CancellationToken cancellationToken = default);
Task<CustomerDto?> CreateAsync(string cafeId, CreateCustomerRequest request, CancellationToken cancellationToken = default);
Task<CustomerDto?> UpdateAsync(string cafeId, string id, UpdateCustomerRequest request, CancellationToken cancellationToken = default);
Task<bool> DeleteAsync(string cafeId, string id, CancellationToken cancellationToken = default);
}
public class CustomerService : ICustomerService
{
private readonly AppDbContext _db;
public CustomerService(AppDbContext db)
{
_db = db;
}
public async Task<IReadOnlyList<CustomerDto>> SearchAsync(
string cafeId,
string? query,
CancellationToken cancellationToken = default)
{
var q = _db.Customers.Where(c => c.CafeId == cafeId && c.DeletedAt == null);
if (!string.IsNullOrWhiteSpace(query))
{
var term = query.Trim();
var normalizedPhone = PhoneNormalizer.Normalize(term);
q = q.Where(c =>
c.Name.Contains(term) ||
c.Phone.Contains(term) ||
(c.NationalId != null && c.NationalId.Contains(term)) ||
(normalizedPhone.Length >= 10 && c.Phone.Contains(normalizedPhone)));
}
var list = await q
.OrderByDescending(c => c.CreatedAt)
.Take(100)
.ToListAsync(cancellationToken);
return list.Select(ToDto).ToList();
}
public async Task<CustomerDto?> GetAsync(string cafeId, string id, CancellationToken cancellationToken = default)
{
var entity = await _db.Customers
.FirstOrDefaultAsync(c => c.Id == id && c.CafeId == cafeId && c.DeletedAt == null, cancellationToken);
return entity is null ? null : ToDto(entity);
}
public async Task<CustomerDto?> CreateAsync(
string cafeId,
CreateCustomerRequest request,
CancellationToken cancellationToken = default)
{
var phone = PhoneNormalizer.Normalize(request.Phone);
var exists = await _db.Customers.AnyAsync(
c => c.CafeId == cafeId && c.Phone == phone, cancellationToken);
if (exists) return null;
var entity = new Customer
{
CafeId = cafeId,
Name = request.Name,
Phone = phone,
NationalId = request.NationalId,
BirthDateJalali = request.BirthDateJalali,
Group = request.Group,
ReferredBy = request.ReferredBy
};
_db.Customers.Add(entity);
await _db.SaveChangesAsync(cancellationToken);
return ToDto(entity);
}
public async Task<CustomerDto?> UpdateAsync(
string cafeId,
string id,
UpdateCustomerRequest request,
CancellationToken cancellationToken = default)
{
var entity = await _db.Customers
.FirstOrDefaultAsync(c => c.Id == id && c.CafeId == cafeId && c.DeletedAt == null, cancellationToken);
if (entity is null) return null;
if (request.Name is not null) entity.Name = request.Name;
if (request.Phone is not null)
{
var phone = PhoneNormalizer.Normalize(request.Phone);
var phoneTaken = await _db.Customers.AnyAsync(
c => c.CafeId == cafeId && c.Phone == phone && c.Id != id && c.DeletedAt == null,
cancellationToken);
if (phoneTaken) return null;
entity.Phone = phone;
}
if (request.NationalId is not null) entity.NationalId = request.NationalId;
if (request.BirthDateJalali is not null) entity.BirthDateJalali = request.BirthDateJalali;
if (request.Group.HasValue) entity.Group = request.Group.Value;
if (request.LoyaltyPoints.HasValue) entity.LoyaltyPoints = request.LoyaltyPoints.Value;
if (request.ReferredBy is not null) entity.ReferredBy = request.ReferredBy;
await _db.SaveChangesAsync(cancellationToken);
return ToDto(entity);
}
public async Task<bool> DeleteAsync(string cafeId, string id, CancellationToken cancellationToken = default)
{
var entity = await _db.Customers
.FirstOrDefaultAsync(c => c.Id == id && c.CafeId == cafeId, cancellationToken);
if (entity is null) return false;
entity.DeletedAt = DateTime.UtcNow;
await _db.SaveChangesAsync(cancellationToken);
return true;
}
private static CustomerDto ToDto(Customer c) => new(
c.Id,
c.Name,
c.Phone,
c.NationalId,
c.BirthDateJalali,
c.Group,
c.LoyaltyPoints,
c.ReferredBy,
c.CreatedAt);
}