using System.Linq.Expressions; using Fake.Application; using Microsoft.AspNetCore.Mvc; using Oms.Application.Dtos.Shared; using Oms.Application.Dtos.System; using Oms.Application.Shared; using Oms.Domain.SystemAggregate.Consts; using Oms.Domain.SystemAggregate.Entities; using Oms.Domain.SystemAggregate.Repositories; namespace Oms.Application.Services.System; /// /// 仓库 API 服务。 /// [ApiExplorerSettings(GroupName = "OMS-System")] public class WarehouseService : ApplicationService { private IWarehouseAddressRepository WarehouseAddressRepository => LazyServiceProvider.GetRequiredService(); private OmsRbacUserDisplayNameResolver UserDisplayNameResolver => LazyServiceProvider.GetRequiredService(); /// /// 查询仓库列表。 /// /// 入参:仓库分页查询条件。 /// 仓库分页结果,包含列表数据和总记录数。 [HttpGet("/system/warehouse/list")] public async Task> GetPaginatedListAsync([FromQuery] WarehousePaginatedInput input) { var predicate = BuildPaginatedPredicate(input); var pageIndex = OmsDocHelper.NormalizePage(input.Page); var pageSize = OmsDocHelper.NormalizePageSize(input.PageSize); var entities = await WarehouseAddressRepository.GetPagedListAsync( predicate, pageIndex, pageSize, new Dictionary { [nameof(WarehouseAddress.UpdateTime)] = false, [nameof(WarehouseAddress.Id)] = false }); var totalCount = await WarehouseAddressRepository.CountAsync(predicate); var items = entities.Select(entity => { var output = ObjectMapper.Map(entity); output.WarehouseTypeName = OmsDocHelper.GetWarehouseTypeName(entity.WarehouseType); output.UpdateTime = OmsDocHelper.NullIfDefault(entity.UpdateTime); return output; }).ToList(); return new OmsPageResult { Items = items, Total = totalCount }; } /// /// 查询仓库详情。 /// /// 入参:目标主键。 /// 仓库详情。 [HttpGet("/system/warehouse/detail")] public async Task GetByIdAsync([FromQuery] int id) { var entity = await GetWarehouseOrThrowAsync(id); var output = ObjectMapper.Map(entity); var auditUserNameMap = await UserDisplayNameResolver.ResolveManyAsync( [entity.CreateUserId, entity.UpdateUserId]); output.CreateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.CreateUserId, auditUserNameMap); output.UpdateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.UpdateUserId, auditUserNameMap); output.UpdateTime = OmsDocHelper.NullIfDefault(entity.UpdateTime); return output; } /// /// 新增仓库。 /// /// 入参:仓库创建参数。 /// 无返回体,仅完成新增仓库。 [HttpPost("/system/warehouse/create")] public async Task CreateAsync(CreateWarehouseInput input) { var warehouseName = input.WarehouseName.Trim(); var duplicatedWarehouse = await WarehouseAddressRepository.GetByWarehouseNameAsync(warehouseName); if (duplicatedWarehouse != null) { throw new BusinessException("仓库名称已存在"); } var deleted = await WarehouseAddressRepository.GetByWarehouseNameIncludingDeletedAsync(warehouseName); if (deleted != null && deleted.IsDeleted) { deleted.IsDeleted = false; deleted.WarehouseName = warehouseName; deleted.WarehouseType = input.WarehouseType; deleted.Recipient = input.Recipient; deleted.ContactPhone = input.ContactPhone; deleted.ShippingAddress = input.ShippingAddress; await WarehouseAddressRepository.UpdateAsync(deleted); return; } var entity = new WarehouseAddress { WarehouseName = warehouseName, WarehouseType = input.WarehouseType, Recipient = input.Recipient, ContactPhone = input.ContactPhone, ShippingAddress = input.ShippingAddress, }; await WarehouseAddressRepository.InsertAsync(entity); } /// /// 更新仓库。 /// /// 入参:仓库更新参数。 /// 无返回体,仅完成更新仓库。 [HttpPost("/system/warehouse/update")] public async Task UpdateAsync(UpdateWarehouseInput input) { var entity = await GetWarehouseOrThrowAsync(input.Id); var warehouseName = input.WarehouseName.Trim(); var duplicatedWarehouse = await WarehouseAddressRepository.GetByWarehouseNameAsync(warehouseName); if (duplicatedWarehouse != null && duplicatedWarehouse.Id != entity.Id) { throw new BusinessException("仓库名称已存在"); } var softDeleted = await WarehouseAddressRepository.GetByWarehouseNameIncludingDeletedAsync(warehouseName); if (softDeleted != null && softDeleted.IsDeleted && softDeleted.Id != entity.Id) { softDeleted.WarehouseName = $"{warehouseName}__deleted_{softDeleted.Id}"; await WarehouseAddressRepository.UpdateAsync(softDeleted); } entity.WarehouseName = warehouseName; entity.WarehouseType = input.WarehouseType; entity.Recipient = input.Recipient; entity.ContactPhone = input.ContactPhone; entity.ShippingAddress = input.ShippingAddress; await WarehouseAddressRepository.UpdateAsync(entity); } /// /// 删除仓库。 /// /// 入参:目标主键。 /// 无返回体,仅完成删除仓库。 [HttpPost("/system/warehouse/delete")] public async Task DeleteAsync(IdInput input) { var entity = await GetWarehouseOrThrowAsync(input.Id); await WarehouseAddressRepository.DeleteAsync(entity); } private Expression> BuildPaginatedPredicate(WarehousePaginatedInput input) { var keyword = input.Keyword?.Trim(); var warehouseType = input.WarehouseType?.Trim(); return warehouse => (string.IsNullOrWhiteSpace(warehouseType) || warehouse.WarehouseType == warehouseType) && (string.IsNullOrWhiteSpace(keyword) || warehouse.WarehouseName.Contains(keyword) || (warehouse.Recipient ?? string.Empty).Contains(keyword) || (warehouse.ContactPhone ?? string.Empty).Contains(keyword)); } private async Task GetWarehouseOrThrowAsync(int id) { var entity = await WarehouseAddressRepository.FirstOrDefaultAsync(x => x.Id == id); if (entity == null) { throw new BusinessException("仓库不存在"); } return entity; } }