using FoodLabeling.Application.Contracts;
using FoodLabeling.Application.Contracts.Dtos.LocationSupport;
using FoodLabeling.Application.Contracts.IServices;
using FoodLabeling.Application.Services.DbModels;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.Guids;
using Volo.Abp.Uow;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace FoodLabeling.Application.Services;
///
/// 全局 Support 联系方式(全门店共用;Web 可增改查,App JWT 仅可读)
///
[Authorize]
public class LocationSupportAppService : ApplicationService, ILocationSupportAppService
{
private readonly ISqlSugarDbContext _dbContext;
private readonly IGuidGenerator _guidGenerator;
public LocationSupportAppService(ISqlSugarDbContext dbContext, IGuidGenerator guidGenerator)
{
_dbContext = dbContext;
_guidGenerator = guidGenerator;
}
///
public async Task GetSupportAsync()
{
var rows = await _dbContext.SqlSugarClient.Queryable()
.Where(x => !x.IsDeleted)
.ToListAsync();
var entity = rows.FirstOrDefault();
return MapOutput(entity);
}
///
[UnitOfWork]
public async Task CreateAsync(LocationSupportCreateInputVo input)
{
EnsureNotUsAppClient();
if (input is null)
{
throw new UserFriendlyException("Request body is required.");
}
var phone = NormalizeRequired(input.SupportPhone, "Support phone is required.");
var email = NormalizeRequired(input.SupportEmail, "Support email is required.");
EnsureEmailFormat(email);
var existed = await _dbContext.SqlSugarClient.Queryable()
.AnyAsync(x => !x.IsDeleted);
if (existed)
{
throw new UserFriendlyException(
"Global support contact already exists. Use update instead.");
}
var now = Clock.Now;
var entity = new FlLocationSupportDbEntity
{
Id = _guidGenerator.Create().ToString(),
IsDeleted = false,
CreationTime = now,
CreatorId = CurrentUser?.Id?.ToString(),
LastModificationTime = now,
LastModifierId = CurrentUser?.Id?.ToString(),
SupportPhone = phone,
SupportEmail = email
};
await _dbContext.SqlSugarClient.Insertable(entity).ExecuteCommandAsync();
return MapOutput(entity)!;
}
///
[UnitOfWork]
public async Task UpdateAsync(string id, LocationSupportUpdateInputVo input)
{
EnsureNotUsAppClient();
var supportId = id?.Trim();
if (string.IsNullOrWhiteSpace(supportId))
{
throw new UserFriendlyException("Support record id is required.");
}
if (input is null)
{
throw new UserFriendlyException("Request body is required.");
}
var rows = await _dbContext.SqlSugarClient.Queryable()
.Where(x => !x.IsDeleted && x.Id == supportId)
.ToListAsync();
var entity = rows.FirstOrDefault();
if (entity is null)
{
throw new UserFriendlyException("Support record not found.");
}
var phone = NormalizeRequired(input.SupportPhone, "Support phone is required.");
var email = NormalizeRequired(input.SupportEmail, "Support email is required.");
EnsureEmailFormat(email);
entity.SupportPhone = phone;
entity.SupportEmail = email;
entity.LastModificationTime = Clock.Now;
entity.LastModifierId = CurrentUser?.Id?.ToString();
await _dbContext.SqlSugarClient.Updateable(entity).ExecuteCommandAsync();
return MapOutput(entity)!;
}
private void EnsureNotUsAppClient()
{
if (CurrentUser.FindClaim(UsAppJwtClaims.ClientKind)?.Value == UsAppJwtClaims.ClientKindUsApp)
{
throw new UserFriendlyException(
"The mobile app can only view support contacts. Please use the web console to edit.");
}
}
private static string NormalizeRequired(string? value, string message)
{
var normalized = value?.Trim();
if (string.IsNullOrWhiteSpace(normalized))
{
throw new UserFriendlyException(message);
}
return normalized;
}
private static void EnsureEmailFormat(string email)
{
if (!email.Contains("@", StringComparison.Ordinal) || email.StartsWith("@", StringComparison.Ordinal) ||
email.EndsWith("@", StringComparison.Ordinal))
{
throw new UserFriendlyException("Support email format is invalid.");
}
}
private static LocationSupportGetOutputDto? MapOutput(FlLocationSupportDbEntity? entity)
{
if (entity is null)
{
return null;
}
return new LocationSupportGetOutputDto
{
Id = entity.Id,
SupportPhone = entity.SupportPhone,
SupportEmail = entity.SupportEmail
};
}
}