using SqlSugar;
using WIDESEA_Common.StockEnum;
using WIDESEA_Core;
using WIDESEA_DTO.MES;
using WIDESEA_DTO.Stock;
using WIDESEA_IBasicService;
using WIDESEA_IStockService;
using WIDESEA_Model.Models;
namespace WIDESEA_StockService
{
///
/// 库存服务聚合实现类
///
public class StockService : IStockService
{
///
/// 库存明细服务
///
public IStockInfoDetailService StockInfoDetailService { get; }
///
/// 库存信息服务
///
public IStockInfoService StockInfoService { get; }
///
/// 库存明细历史服务
///
public IStockInfoDetail_HtyService StockInfoDetail_HtyService { get; }
///
/// 库存历史服务
///
public IStockInfo_HtyService StockInfo_HtyService { get; }
///
/// Mes接口服务
///
public IMesService _mesService { get; }
///
/// 构造函数
///
/// 库存明细服务
/// 库存信息服务
/// 库存明细历史服务
/// 库存历史服务
public StockService(
IStockInfoDetailService stockInfoDetailService,
IStockInfoService stockInfoService,
IStockInfoDetail_HtyService stockInfoDetail_HtyService,
IStockInfo_HtyService stockInfo_HtyService,
IMesService mesService)
{
StockInfoDetailService = stockInfoDetailService;
StockInfoService = stockInfoService;
StockInfoDetail_HtyService = stockInfoDetail_HtyService;
StockInfo_HtyService = stockInfo_HtyService;
_mesService = mesService;
}
///
/// 在事务中执行操作
///
private async Task ExecuteWithinTransactionAsync(Func> operation)
{
var db = StockInfoService.Repository.Db as SqlSugarClient;
if (db == null)
{
return WebResponseContent.Instance.Error("Database context does not support transactions");
}
var ownsTransaction = db.Ado.Transaction == null;
try
{
if (ownsTransaction)
{
db.BeginTran();
}
var result = await operation();
if (result?.Status == true)
{
if (ownsTransaction)
{
db.CommitTran();
}
return result;
}
if (ownsTransaction)
{
db.RollbackTran();
}
return result ?? WebResponseContent.Instance.Error("Transaction failed");
}
catch
{
if (ownsTransaction)
{
db.RollbackTran();
}
throw;
}
}
///
/// 组盘
///
public async Task GroupPalletAsync(StockDTO stock)
{
WebResponseContent content = new WebResponseContent();
try
{
var now = DateTime.Now;
var details = stock.Details.Select(item => new Dt_StockInfoDetail
{
MaterielCode = "电芯",
MaterielName = "电芯",
StockQuantity = item.Quantity,
Unit = "PCS",
Creater = "system",
OrderNo = "111",
ProductionDate = now.ToString(),
EffectiveDate = now.AddYears(1).ToString(),
SerialNumber = item.CellBarcode,
InboundOrderRowNo = item.Channel,
Status = StockStatusEmun.组盘暂存.GetHashCode(),
}).ToList();
var bindRequest = new BindContainerRequest
{
ContainerCode = stock?.TargetPalletNo,
EquipmentCode = "STK-GROUP-001",
ResourceCode = "STK-GROUP-001",
LocalTime = now,
OperationType = 0, // 0代表组盘
ContainerSfcList = details.Select(d => new ContainerSfcItem
{
Sfc = d.SerialNumber,
Location = d.InboundOrderRowNo.ToString(),
}).ToList()
};
return await ExecuteWithinTransactionAsync(async () =>
{
var existingStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.TargetPalletNo);
var result = false;
if (existingStock != null)
{
details.ForEach(d => d.StockId = existingStock.Id);
result = await StockInfoDetailService.Repository.AddDataAsync(details) > 0;
return result ? content.OK("组盘成功") : content.Error("组盘失败");
}
var entity = new Dt_StockInfo
{
PalletCode = stock.TargetPalletNo,
//WarehouseId = stock.WarehouseId > 0 ? stock.WarehouseId : 1,
WarehouseId = 1,
StockStatus = StockStatusEmun.组盘暂存.GetHashCode(),
Creater = "system",
Details = details
};
var mesResult = _mesService.BindContainer(bindRequest);
if (mesResult == null || !mesResult.IsSuccess)
{
return content.Error($"组盘成功,但MES绑定失败: {mesResult?.ErrorMessage ?? "未知错误"}");
}
result = StockInfoService.Repository.AddData(entity, x => x.Details);
return result ? content.OK("组盘成功") : content.Error("组盘失败");
});
}
catch (Exception ex)
{
return content.Error($"组盘失败: {ex.Message}");
}
}
///
/// 换盘
///
public async Task ChangePalletAsync(StockDTO stock)
{
WebResponseContent content = new WebResponseContent();
try
{
if (stock == null ||
string.IsNullOrWhiteSpace(stock.TargetPalletNo) ||
string.IsNullOrWhiteSpace(stock.SourcePalletNo) ||
string.Equals(stock.SourcePalletNo, stock.TargetPalletNo, StringComparison.OrdinalIgnoreCase))
{
return content.Error("源托盘号与目标托盘号相同");
}
return await ExecuteWithinTransactionAsync(async () =>
{
var sourceStock = await StockInfoService.Repository.QueryDataNavFirstAsync(s => s.PalletCode == stock.SourcePalletNo);
if (sourceStock == null) return content.Error("源托盘不存在");
var targetStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.TargetPalletNo);
if (targetStock == null)
{
var newStock = new Dt_StockInfo
{
PalletCode = stock.TargetPalletNo,
WarehouseId = sourceStock.WarehouseId,
StockStatus = StockStatusEmun.组盘暂存.GetHashCode(),
Creater = "system",
};
var newId = StockInfoService.Repository.AddData(newStock);
if (newId <= 0) return content.Error("换盘失败");
targetStock = newStock;
targetStock.Id = newId;
}
var serialNumbers = stock.Details.Select(d => d.Channel).Distinct().ToList();
if (!serialNumbers.Any()) return content.Error("未找到有效的序列号");
var detailEntities = StockInfoDetailService.Repository.QueryData(
d => d.StockId == sourceStock.Id && serialNumbers.Contains(d.InboundOrderRowNo));
if (!detailEntities.Any()) return content.Error("未找到有效的库存明细");
if (await StockInfoDetail_HtyService.Repository.AddDataAsync(CreateDetailHistory(detailEntities, "换盘")) <= 0)
return content.Error("换盘历史记录保存失败");
if (await StockInfo_HtyService.Repository.AddDataAsync(CreateStockHistory(new[] { sourceStock, targetStock }, "换盘")) <= 0)
return content.Error("换盘历史记录保存失败");
detailEntities.ForEach(d => d.StockId = targetStock.Id);
var result = await StockInfoDetailService.Repository.UpdateDataAsync(detailEntities);
if (!result) return content.Error("换盘失败");
return content.OK("换盘成功");
});
}
catch (Exception ex)
{
return content.Error($"换盘失败: {ex.Message}");
}
}
///
/// 拆盘
///
public async Task SplitPalletAsync(StockDTO stock)
{
WebResponseContent content = new WebResponseContent();
try
{
if (stock == null || string.IsNullOrWhiteSpace(stock.SourcePalletNo))
return content.Error("源托盘号不能为空");
return await ExecuteWithinTransactionAsync(async () =>
{
var sourceStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.SourcePalletNo);
if (sourceStock == null) return content.Error("源托盘不存在");
var serialNumbers = stock.Details.Select(d => d.CellBarcode).Distinct().ToList();
if (!serialNumbers.Any())
{
serialNumbers = sourceStock.Details
.Where(x => stock.Details.Any(d => d.Channel == x.InboundOrderRowNo))
.Select(x => x.SerialNumber)
.ToList();
}
var detailEntities = StockInfoDetailService.Repository.QueryData(
d => d.StockId == sourceStock.Id && serialNumbers.Contains(d.SerialNumber));
if (!detailEntities.Any()) return content.Error("未找到有效的库存明细");
if (await StockInfoDetail_HtyService.Repository.AddDataAsync(CreateDetailHistory(detailEntities, "拆盘")) <= 0)
return content.Error("拆盘历史记录保存失败");
if (await StockInfo_HtyService.Repository.AddDataAsync(CreateStockHistory(new[] { sourceStock }, "拆盘")) <= 0)
return content.Error("拆盘历史记录保存失败");
var result = await StockInfoDetailService.Repository.DeleteDataAsync(detailEntities);
if (!result) return content.Error("拆盘失败");
return content.OK("拆盘成功");
});
}
catch (Exception ex)
{
return content.Error($"拆盘失败: {ex.Message}");
}
}
///
/// 堆垛机换盘后更新库存信息(清空库位信息)
///
///
///
public async Task UpdateStockInfoAsync(StockInfoDTO stock)
{
WebResponseContent content = new WebResponseContent();
if (string.IsNullOrWhiteSpace(stock.PalletCode)) return content.Error("托盘号不能为空");
var existingStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.PalletCode);
if (existingStock == null) return content.Error("托盘信息不存在");
existingStock.LocationCode = "";
existingStock.LocationId = 0;
var result = await StockInfoService.Repository.UpdateDataAsync(existingStock);
if (!result) return content.Error("更新库存信息失败");
return content.OK("更新库存信息成功");
}
private static List CreateDetailHistory(IEnumerable details, string operateType)
{
var now = DateTime.Now;
return details.Select(d => new Dt_StockInfoDetail_Hty
{
SourceId = d.Id,
OperateType = operateType,
InsertTime = now,
StockId = d.StockId,
MaterielCode = d.MaterielCode,
MaterielName = d.MaterielName,
OrderNo = d.OrderNo,
BatchNo = d.BatchNo,
ProductionDate = d.ProductionDate,
EffectiveDate = d.EffectiveDate,
SerialNumber = d.SerialNumber,
StockQuantity = d.StockQuantity,
OutboundQuantity = d.OutboundQuantity,
Status = d.Status,
Unit = d.Unit,
InboundOrderRowNo = d.InboundOrderRowNo,
Remark = d.Remark,
Creater = d.Creater,
CreateDate = d.CreateDate,
Modifier = d.Modifier,
ModifyDate = d.ModifyDate
}).ToList();
}
private static List CreateStockHistory(IEnumerable stocks, string operateType)
{
var now = DateTime.Now;
return stocks.Select(s => new Dt_StockInfo_Hty
{
SourceId = s.Id,
OperateType = operateType,
InsertTime = now,
PalletCode = s.PalletCode,
PalletType = s.PalletType,
LocationCode = s.LocationCode,
WarehouseId = s.WarehouseId,
StockStatus = s.StockStatus,
Remark = s.Remark,
Creater = s.Creater,
CreateDate = s.CreateDate,
Modifier = s.Modifier,
ModifyDate = s.ModifyDate,
LocationId = s.LocationId,
OutboundDate = s.OutboundDate
}).ToList();
}
}
}