| | |
| | | using WIDESEA_Common.StockEnum; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_DTO.Stock; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IRecordService; |
| | | using WIDESEA_IStockService; |
| | | using WIDESEA_Model.Models; |
| | | |
| | |
| | | /// 仓库信息服务接口(用于获取仓库基本信息) |
| | | /// </summary> |
| | | private readonly IWarehouseService _warehouseService; |
| | | private readonly IRecordService _recordService; |
| | | private readonly IUnitOfWorkManage _unitOfWorkManage; |
| | | private readonly IStockInfoDetailService _stockInfoDetailService; |
| | | |
| | | /// <summary> |
| | | /// 构造函数 |
| | | /// </summary> |
| | | /// <param name="baseDal">基础数据访问对象</param> |
| | | public StockInfoService(IRepository<Dt_StockInfo> baseDal, ILocationInfoService locationInfoService, IWarehouseService warehouseService) : base(baseDal) |
| | | public StockInfoService( |
| | | IRepository<Dt_StockInfo> baseDal, |
| | | ILocationInfoService locationInfoService, |
| | | IWarehouseService warehouseService, |
| | | IRecordService recordService, |
| | | IUnitOfWorkManage unitOfWorkManage, |
| | | IStockInfoDetailService stockInfoDetailService) : base(baseDal) |
| | | { |
| | | _locationInfoService = locationInfoService; |
| | | _warehouseService = warehouseService; |
| | | _recordService = recordService; |
| | | _unitOfWorkManage = unitOfWorkManage; |
| | | _stockInfoDetailService = stockInfoDetailService; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | /// <returns>更新是否成功</returns> |
| | | public async Task<bool> UpdateStockAsync(Dt_StockInfo stockInfo) |
| | | { |
| | | return await BaseDal.UpdateDataAsync(stockInfo); |
| | | var beforeStock = await BaseDal.QueryDataNavFirstAsync(x => x.Id == stockInfo.Id); |
| | | var result = await BaseDal.UpdateDataAsync(stockInfo); |
| | | if (!result) |
| | | return false; |
| | | |
| | | var afterStock = await BaseDal.QueryDataNavFirstAsync(x => x.Id == stockInfo.Id) ?? stockInfo; |
| | | var changeType = ResolveChangeType(beforeStock, afterStock); |
| | | return await _recordService.AddStockChangeRecordAsync(beforeStock, afterStock, changeType, remark: "库存更新"); |
| | | } |
| | | |
| | | public override WebResponseContent AddData(Dt_StockInfo entity) |
| | | { |
| | | var result = base.AddData(entity); |
| | | if (!result.Status) |
| | | return result; |
| | | |
| | | var saveRecordResult = _recordService.AddStockChangeRecordAsync(null, entity, StockChangeTypeEnum.Inbound, remark: "库存新增").GetAwaiter().GetResult(); |
| | | return saveRecordResult ? result : WebResponseContent.Instance.Error("库存变更记录保存失败"); |
| | | } |
| | | |
| | | public override WebResponseContent UpdateData(Dt_StockInfo entity) |
| | | { |
| | | var beforeStock = BaseDal.QueryFirst(x => x.Id == entity.Id); |
| | | var result = base.UpdateData(entity); |
| | | if (!result.Status) |
| | | return result; |
| | | |
| | | var changeType = ResolveChangeType(beforeStock, entity); |
| | | var saveRecordResult = _recordService.AddStockChangeRecordAsync(beforeStock, entity, changeType, remark: "库存更新").GetAwaiter().GetResult(); |
| | | return saveRecordResult ? result : WebResponseContent.Instance.Error("库存变更记录保存失败"); |
| | | } |
| | | |
| | | public override WebResponseContent DeleteData(Dt_StockInfo entity) |
| | | { |
| | | var beforeStock = CloneStockSnapshot(entity); |
| | | var result = base.DeleteData(entity); |
| | | if (!result.Status) |
| | | return result; |
| | | |
| | | var saveRecordResult = _recordService.AddStockChangeRecordAsync(beforeStock, null, StockChangeTypeEnum.Outbound, remark: "库存删除").GetAwaiter().GetResult(); |
| | | return saveRecordResult ? result : WebResponseContent.Instance.Error("库存变更记录保存失败"); |
| | | } |
| | | |
| | | private static StockChangeTypeEnum ResolveChangeType(Dt_StockInfo? beforeStock, Dt_StockInfo? afterStock) |
| | | { |
| | | if (beforeStock == null) |
| | | return StockChangeTypeEnum.Inbound; |
| | | |
| | | if (afterStock == null) |
| | | return StockChangeTypeEnum.Outbound; |
| | | |
| | | if (!string.Equals(beforeStock.LocationCode, afterStock.LocationCode, StringComparison.OrdinalIgnoreCase)) |
| | | return StockChangeTypeEnum.Relocation; |
| | | |
| | | if (beforeStock.StockStatus != afterStock.StockStatus) |
| | | return StockChangeTypeEnum.StockLock; |
| | | |
| | | var beforeQuantity = beforeStock.Details?.Sum(x => x.StockQuantity) ?? 0; |
| | | var afterQuantity = afterStock.Details?.Sum(x => x.StockQuantity) ?? 0; |
| | | return afterQuantity >= beforeQuantity ? StockChangeTypeEnum.Inbound : StockChangeTypeEnum.Outbound; |
| | | } |
| | | |
| | | private static Dt_StockInfo CloneStockSnapshot(Dt_StockInfo stockInfo) |
| | | { |
| | | return new Dt_StockInfo |
| | | { |
| | | Id = stockInfo.Id, |
| | | PalletCode = stockInfo.PalletCode, |
| | | PalletType = stockInfo.PalletType, |
| | | LocationId = stockInfo.LocationId, |
| | | LocationCode = stockInfo.LocationCode, |
| | | WarehouseId = stockInfo.WarehouseId, |
| | | StockStatus = stockInfo.StockStatus, |
| | | Remark = stockInfo.Remark, |
| | | OutboundDate = stockInfo.OutboundDate, |
| | | Details = stockInfo.Details?.Select(detail => new Dt_StockInfoDetail |
| | | { |
| | | Id = detail.Id, |
| | | StockId = detail.StockId, |
| | | MaterielCode = detail.MaterielCode, |
| | | MaterielName = detail.MaterielName, |
| | | OrderNo = detail.OrderNo, |
| | | BatchNo = detail.BatchNo, |
| | | ProductionDate = detail.ProductionDate, |
| | | EffectiveDate = detail.EffectiveDate, |
| | | SerialNumber = detail.SerialNumber, |
| | | StockQuantity = detail.StockQuantity, |
| | | OutboundQuantity = detail.OutboundQuantity, |
| | | Status = detail.Status, |
| | | Unit = detail.Unit, |
| | | InboundOrderRowNo = detail.InboundOrderRowNo, |
| | | Remark = detail.Remark |
| | | }).ToList() |
| | | }; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | Locations = locationItems |
| | | }; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 使用事务删除库存和明细信息(先查询再删除) |
| | | /// </summary> |
| | | /// <param name="stockId">库存ID</param> |
| | | /// <returns>删除结果</returns> |
| | | public async Task<WebResponseContent> DeleteStockWithDetailsAsync(int stockId) |
| | | { |
| | | if (stockId <= 0) |
| | | return WebResponseContent.Instance.Error("库存ID无效"); |
| | | |
| | | _unitOfWorkManage.BeginTran(); |
| | | try |
| | | { |
| | | // 先查询库存信息(包含明细) |
| | | var stockInfo = await BaseDal.QueryDataNavFirstAsync(x => x.Id == stockId); |
| | | if (stockInfo == null) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return WebResponseContent.Instance.Error("库存记录不存在"); |
| | | } |
| | | |
| | | // 查询并删除库存明细记录 |
| | | var existingDetails = await _stockInfoDetailService.Repository.QueryDataAsync(x => x.StockId == stockId); |
| | | if (existingDetails != null && existingDetails.Any()) |
| | | { |
| | | var deleteDetailResult = await _stockInfoDetailService.Repository.DeleteDataAsync(existingDetails); |
| | | if (!deleteDetailResult) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return WebResponseContent.Instance.Error("删除库存明细记录失败"); |
| | | } |
| | | } |
| | | |
| | | // 删除库存主记录 |
| | | var deleteStockResult = await BaseDal.DeleteDataAsync(stockInfo); |
| | | if (!deleteStockResult) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return WebResponseContent.Instance.Error("删除库存主记录失败"); |
| | | } |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | // 记录库存变更日志 |
| | | var saveRecordResult = await _recordService.AddStockChangeRecordAsync(stockInfo, null, StockChangeTypeEnum.Outbound, remark: "库存删除"); |
| | | if (!saveRecordResult) |
| | | { |
| | | return WebResponseContent.Instance.Error("库存变更记录保存失败"); |
| | | } |
| | | |
| | | return WebResponseContent.Instance.OK("库存删除成功"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return WebResponseContent.Instance.Error($"删除库存和明细时发生异常: {ex.Message}"); |
| | | } |
| | | } |
| | | } |
| | | } |