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 }; } }