using Dm.filter;
|
using MailKit.Search;
|
using Microsoft.AspNetCore.Http;
|
using SqlSugar;
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
using WIDESEA_Common.LocationEnum;
|
using WIDESEA_Common.OrderEnum;
|
using WIDESEA_Common.StockEnum;
|
using WIDESEA_Core;
|
using WIDESEA_Core.BaseRepository;
|
using WIDESEA_Core.BaseServices;
|
using WIDESEA_Core.Helper;
|
using WIDESEA_DTO.Outbound;
|
using WIDESEA_IBasicService;
|
using WIDESEA_IOutboundService;
|
using WIDESEA_IStockService;
|
using WIDESEA_Model.Models;
|
|
namespace WIDESEA_OutboundService
|
{
|
/// <summary>
|
///
|
/// </summary>
|
public class OutboundPickingService : ServiceBase<Dt_PickingRecord, IRepository<Dt_PickingRecord>>, IOutboundPickingService
|
{
|
private readonly IUnitOfWorkManage _unitOfWorkManage;
|
public IRepository<Dt_PickingRecord> Repository => BaseDal;
|
|
private readonly IStockInfoService _stockInfoService;
|
private readonly IStockService _stockService;
|
private readonly IOutStockLockInfoService _outStockLockInfoService;
|
private readonly IStockInfoDetailService _stockInfoDetailService;
|
private readonly ILocationInfoService _locationInfoService;
|
private readonly IOutboundOrderDetailService _outboundOrderDetailService;
|
private readonly IOutboundOrderService _outboundOrderService;
|
private readonly ISplitPackageService _splitPackageService;
|
private readonly IRepository<Dt_Task> _taskRepository;
|
|
|
public OutboundPickingService(IRepository<Dt_PickingRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IStockService stockService, IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, ILocationInfoService locationInfoService, IOutboundOrderDetailService outboundOrderDetailService, ISplitPackageService splitPackageService, IOutboundOrderService outboundOrderService, IRepository<Dt_Task> taskRepository) : base(BaseDal)
|
{
|
_unitOfWorkManage = unitOfWorkManage;
|
_stockInfoService = stockInfoService;
|
_stockService = stockService;
|
_outStockLockInfoService = outStockLockInfoService;
|
_stockInfoDetailService = stockInfoDetailService;
|
_locationInfoService = locationInfoService;
|
_outboundOrderDetailService = outboundOrderDetailService;
|
_splitPackageService = splitPackageService;
|
_outboundOrderService = outboundOrderService;
|
_taskRepository = taskRepository;
|
}
|
|
|
#region 查询出库详情列表
|
public async Task<List<OutStockLockListResp>> GetOutStockLockListAsync(string orderNo)
|
{
|
var locks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(t => t.OrderNo == orderNo)
|
.ToListAsync();
|
|
return locks.Select(t => new OutStockLockListResp
|
{
|
Id = t.Id,
|
// TaskNum = t.TaskNum,
|
PalletCode = t.PalletCode,
|
CurrentBarcode = t.CurrentBarcode,
|
AssignQuantity = t.AssignQuantity,
|
PickedQty = t.PickedQty,
|
Status = t.Status,
|
// IsSplitted = t.IsSplitted
|
}).ToList();
|
}
|
#endregion
|
public async Task<WebResponseContent> ValidateBarcode(string barcode)
|
{
|
try
|
{
|
if (string.IsNullOrEmpty(barcode))
|
{
|
return WebResponseContent.Instance.Error("条码不能为空");
|
}
|
|
// 根据条码查询库存明细
|
var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
|
.Includes(x => x.StockInfo)
|
.Where(x => x.Barcode == barcode)
|
.FirstAsync();
|
|
if (stockDetail == null)
|
{
|
return WebResponseContent.Instance.Error("条码不存在");
|
}
|
|
|
|
var result = new
|
{
|
Barcode = barcode,
|
MaterielCode = stockDetail.MaterielCode,
|
|
BatchNo = stockDetail.BatchNo,
|
AvailableQuantity = stockDetail.StockQuantity - stockDetail.OutboundQuantity,
|
LocationCode = stockDetail.StockInfo?.LocationCode,
|
PalletCode = stockDetail.StockInfo?.PalletCode
|
};
|
|
return WebResponseContent.Instance.OK(null, result);
|
}
|
catch (Exception ex)
|
{
|
return WebResponseContent.Instance.Error($"条码验证失败: {ex.Message}");
|
}
|
}
|
|
/// <summary>
|
/// 扫码拣选确认
|
/// </summary>
|
public async Task<WebResponseContent> ConfirmPicking(PickingConfirmRequest request)
|
{
|
try
|
{
|
_unitOfWorkManage.BeginTran();
|
|
// 1. 验证条码有效性
|
var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
|
.Where(x => x.Barcode == request.Barcode && x.MaterielCode == request.MaterielCode)
|
.FirstAsync();
|
|
if (stockDetail == null)
|
return WebResponseContent.Instance.Error("无效的条码或物料编码");
|
|
// 2. 检查库存可用数量
|
decimal availableQuantity = stockDetail.StockQuantity - stockDetail.OutboundQuantity;
|
if (request.PickQuantity > availableQuantity)
|
return WebResponseContent.Instance.Error($"拣选数量超过可用库存,可用数量:{availableQuantity}");
|
|
// 3. 查找相关的出库锁定信息(支持拆包后的新条码)
|
var lockInfo = await FindLockInfoByBarcode(request.OrderDetailId, request.Barcode, request.MaterielCode);
|
|
if (lockInfo == null)
|
return WebResponseContent.Instance.Error("未找到相关的出库锁定信息");
|
|
// 4. 检查锁定数量
|
decimal remainingLockQuantity = lockInfo.AssignQuantity - lockInfo.PickedQty;
|
if (request.PickQuantity > remainingLockQuantity)
|
return WebResponseContent.Instance.Error($"拣选数量超过锁定数量,剩余可拣选:{remainingLockQuantity}");
|
|
// 5. 更新锁定信息的已拣选数量
|
lockInfo.PickedQty += request.PickQuantity;
|
await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
|
|
// 6. 更新库存出库数量 - 实际减少库存
|
stockDetail.OutboundQuantity += request.PickQuantity;
|
await _stockInfoService.Db.Updateable(stockDetail).ExecuteCommandAsync();
|
|
// 7. 更新出库单明细
|
var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
|
.Where(x => x.Id == request.OrderDetailId)
|
.FirstAsync();
|
|
orderDetail.OverOutQuantity += request.PickQuantity;
|
orderDetail.LockQuantity -= request.PickQuantity;
|
|
// 检查是否完成出库
|
if (Math.Abs(orderDetail.OverOutQuantity - orderDetail.OrderQuantity) < 0.001m)
|
{
|
orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.Over;
|
orderDetail.LockQuantity = 0;
|
|
// 更新相关的锁定信息状态为已出库
|
var relatedLockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.OrderDetailId == request.OrderDetailId &&
|
x.Status == (int)OutLockStockStatusEnum.出库中)
|
.ToListAsync();
|
|
foreach (var relatedLock in relatedLockInfos)
|
{
|
relatedLock.Status = (int)OutLockStockStatusEnum.已出库;
|
}
|
await _outStockLockInfoService.Db.Updateable(relatedLockInfos).ExecuteCommandAsync();
|
}
|
|
await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
|
|
// 8. 记录拣选历史
|
var pickHistory = new Dt_PickingRecord
|
{
|
OrderDetailId = request.OrderDetailId,
|
Barcode = request.Barcode,
|
PickQuantity = request.PickQuantity,
|
PickTime = DateTime.Now,
|
|
LocationCode = request.LocationCode,
|
StockId = stockDetail.StockId
|
};
|
await Db.Insertable(pickHistory).ExecuteCommandAsync();
|
|
_unitOfWorkManage.CommitTran();
|
|
return WebResponseContent.Instance.OK("拣选确认成功");
|
}
|
catch (Exception ex)
|
{
|
_unitOfWorkManage.RollbackTran();
|
return WebResponseContent.Instance.Error($"拣选确认失败: {ex.Message}");
|
}
|
}
|
|
public async Task<WebResponseContent> ConfirmPicking(string orderNo, string palletCode, string barcode)
|
{
|
try
|
{
|
_unitOfWorkManage.BeginTran();
|
// 1. 验证条码有效性
|
var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
|
.Where(x => x.Barcode == barcode)
|
.FirstAsync();
|
|
if (stockDetail == null)
|
return WebResponseContent.Instance.Error("无效的条码或物料编码");
|
|
//// 2. 检查库存可用数量
|
//var availableQty = stockDetail.StockQuantity - stockDetail.OutboundQuantity;
|
//if (availableQty <= 0)
|
// return WebResponseContent.Instance.Error("库存数量不足");
|
|
// 3. 查找相关的出库详情信息
|
var outStockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.OrderNo == orderNo &&
|
x.PalletCode == palletCode &&
|
x.CurrentBarcode == barcode &&
|
x.Status == (int)OutLockStockStatusEnum.出库中 &&
|
x.AssignQuantity - x.PickedQty > 0)
|
.FirstAsync();
|
|
|
if (outStockInfo == null)
|
return WebResponseContent.Instance.Error("未找到对应的拣选信息或已拣选完成");
|
|
// 4. 检查出库详情锁定数量
|
if (outStockInfo.RemainQuantity <= 0)
|
return WebResponseContent.Instance.Error("该条码已无剩余可拣选数量");
|
|
// 5. 更新出库详情的已拣选数量
|
outStockInfo.PickedQty = outStockInfo.AssignQuantity;
|
outStockInfo.Status = (int)OutLockStockStatusEnum.已拣选;
|
await _outStockLockInfoService.Db.Updateable(outStockInfo).ExecuteCommandAsync();
|
|
//// 6. 更新库存出库数量
|
//await _stockInfoDetailService.Db.Updateable<Dt_StockInfoDetail>()
|
// .SetColumns(x => x.OutboundQuantity == x.OutboundQuantity + outStockInfo.AssignQuantity)
|
// .Where(x => x.Id == stockDetail.Id)
|
// .ExecuteCommandAsync();
|
|
// 7. 更新出库单明细
|
var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
|
.Where(x => x.Id == outStockInfo.OrderDetailId)
|
.FirstAsync();
|
if (orderDetail != null)
|
{
|
orderDetail.OverOutQuantity += outStockInfo.AssignQuantity;
|
orderDetail.LockQuantity -= outStockInfo.AssignQuantity;
|
await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
|
}
|
// 8. 检查是否完成出库
|
await CheckAndUpdateOrderStatus(orderNo);
|
|
//查询任务表
|
var task = _taskRepository.QueryData(x => x.OrderNo == orderNo && x.PalletCode == palletCode).FirstOrDefault();
|
// 9. 记录拣选历史
|
var pickingHistory = new Dt_PickingRecord
|
{
|
FactoryArea = outStockInfo.FactoryArea,
|
TaskNo = task?.TaskNum ?? 0,
|
LocationCode = task?.SourceAddress ?? "",
|
StockId = stockDetail.Id,
|
OrderNo = orderNo,
|
OrderDetailId = orderDetail?.Id ?? 0,
|
PalletCode = palletCode,
|
Barcode = barcode,
|
MaterielCode = outStockInfo.MaterielCode,
|
PickQuantity = outStockInfo.AssignQuantity,
|
PickTime = DateTime.Now,
|
Operator = App.User.UserName,
|
OutStockLockId = outStockInfo.Id
|
};
|
await Db.Insertable(pickingHistory).ExecuteCommandAsync();
|
|
_unitOfWorkManage.CommitTran();
|
return WebResponseContent.Instance.OK("拣选确认成功");
|
|
}
|
catch (Exception ex)
|
{
|
return WebResponseContent.Instance.Error($"拣选确认失败:{ex.Message}");
|
}
|
}
|
// 检查并更新订单状态
|
private async Task CheckAndUpdateOrderStatus(string orderNo)
|
{
|
|
|
var orderDetails = await _stockInfoDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
|
.Where(x => x.OrderId == orderNo.ObjToInt())
|
.ToListAsync();
|
|
bool allCompleted = true;
|
foreach (var detail in orderDetails)
|
{
|
if (detail.OverOutQuantity < detail.NeedOutQuantity)
|
{
|
allCompleted = false;
|
break;
|
}
|
}
|
|
if (allCompleted)
|
{
|
await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
|
.SetColumns(x => x.OrderStatus == 2) // 已完成
|
.Where(x => x.OrderNo == orderNo)
|
.ExecuteCommandAsync();
|
}
|
}
|
// 取消拣选功能
|
public async Task<WebResponseContent> CancelPicking(string orderNo, string palletCode, string barcode)
|
{
|
try
|
{
|
_unitOfWorkManage.BeginTran();
|
// 查找拣选记录
|
var outStockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.OrderNo == orderNo &&
|
x.PalletCode == palletCode &&
|
x.CurrentBarcode == barcode &&
|
x.Status == 2)
|
.FirstAsync();
|
|
if (outStockInfo == null)
|
return WebResponseContent.Instance.Error("未找到已拣选记录");
|
|
// 还原出库详情状态
|
outStockInfo.PickedQty = 0;
|
outStockInfo.Status = 1;
|
await _outStockLockInfoService.Db.Updateable(outStockInfo).ExecuteCommandAsync();
|
|
//// 还原库存出库数量
|
//await _stockInfoDetailService.Db.Updateable<Dt_StockInfoDetail>()
|
// .SetColumns(x => x.OutboundQuantity == x.OutboundQuantity - outStockInfo.AssignQuantity)
|
// .Where(x => x.Barcode == barcode)
|
// .ExecuteCommandAsync();
|
|
// 还原出库单明细
|
var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
|
.Where(x => x.Id == outStockInfo.OrderDetailId)
|
.FirstAsync();
|
|
orderDetail.OverOutQuantity -= outStockInfo.AssignQuantity;
|
await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
|
|
// 删除拣选历史
|
await Db.Deleteable<Dt_PickingRecord>()
|
.Where(x => x.OutStockLockId == outStockInfo.Id)
|
.ExecuteCommandAsync();
|
|
_unitOfWorkManage.CommitTran();
|
return WebResponseContent.Instance.OK("取消拣选成功");
|
|
}
|
catch (Exception ex)
|
{
|
return WebResponseContent.Instance.Error($"取消拣选失败:{ex.Message}");
|
}
|
}
|
/// <summary>
|
/// 根据条码查找锁定信息
|
/// </summary>
|
private async Task<Dt_OutStockLockInfo> FindLockInfoByBarcode(int orderDetailId, string barcode, string materielCode)
|
{
|
return await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.OrderDetailId == orderDetailId &&
|
x.MaterielCode == materielCode &&
|
x.CurrentBarcode == barcode &&
|
x.Status == (int)OutLockStockStatusEnum.出库中 &&
|
x.AssignQuantity > x.PickedQty)
|
.FirstAsync();
|
}
|
|
// 获取未拣选列表
|
public async Task<List<Dt_OutStockLockInfo>> GetUnpickedList(string orderNo, string palletCode)
|
{
|
var list = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.OrderNo == orderNo &&
|
x.PalletCode == palletCode &&
|
x.Status == 1)
|
.ToListAsync();
|
return list.Where(x => x.RemainQuantity > 0).ToList();
|
}
|
|
// 获取已拣选列表
|
public async Task<List<Dt_OutStockLockInfo>> GetPickedList(string orderNo, string palletCode)
|
{
|
var list = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.OrderNo == orderNo &&
|
x.PalletCode == palletCode &&
|
x.Status == 2)
|
.ToListAsync();
|
return list;
|
}
|
|
public async Task<object> GetPickingSummary(string orderNo, string palletCode)
|
{
|
var summary = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.OrderNo == orderNo &&
|
x.PalletCode == palletCode && x.Status == 1)
|
.GroupBy(x => new { x.PalletCode, x.MaterielCode })
|
.Select(x => new
|
{
|
PalletCode = x.PalletCode,
|
MaterielCode = x.MaterielCode,
|
UnpickedCount = SqlFunc.AggregateCount(x.Id),
|
UnpickedQuantity = SqlFunc.AggregateSum(x.AssignQuantity) - SqlFunc.AggregateSum(x.PickedQty)
|
})
|
.FirstAsync();
|
|
return summary;
|
}
|
|
// 获取拣选汇总
|
public async Task<object> GetPickingSummary(ConfirmPickingDto dto)
|
{
|
var picked = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.WhereIF(!string.IsNullOrEmpty(dto.OrderNo), x => x.OrderNo == dto.OrderNo)
|
.WhereIF(!string.IsNullOrEmpty(dto.PalletCode), x => x.PalletCode == dto.PalletCode)
|
.Where(x => x.Status == 2)
|
.GroupBy(x => new { x.PalletCode, x.MaterielCode })
|
.Select(x => new SummaryPickingDto
|
{
|
PalletCode = x.PalletCode,
|
MaterielCode = x.MaterielCode,
|
pickedCount = SqlFunc.AggregateCount(x.Id)
|
}).FirstAsync();
|
if (picked == null)
|
{
|
picked = new SummaryPickingDto { pickedCount = 0 };
|
}
|
|
var summary = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.WhereIF(!string.IsNullOrEmpty(dto.OrderNo), x => x.OrderNo == dto.OrderNo)
|
.WhereIF(!string.IsNullOrEmpty(dto.PalletCode), x => x.PalletCode == dto.PalletCode)
|
.Where(x => x.Status == 1)
|
.GroupBy(x => new { x.PalletCode, x.MaterielCode })
|
.Select(x => new SummaryPickingDto
|
{
|
PalletCode = x.PalletCode,
|
MaterielCode = x.MaterielCode,
|
UnpickedCount = SqlFunc.AggregateCount(x.Id),
|
UnpickedQuantity = SqlFunc.AggregateSum(x.AssignQuantity) - SqlFunc.AggregateSum(x.PickedQty),
|
|
}).FirstAsync();
|
if (summary == null)
|
{
|
summary = new SummaryPickingDto { pickedCount = 0 };
|
}
|
summary.pickedCount = picked.pickedCount;
|
|
return summary;
|
}
|
/// <summary>
|
/// 获取拣选历史
|
/// </summary>
|
public async Task<List<Dt_PickingRecord>> GetPickingHistory(int orderId)
|
{
|
// 通过出库单ID查询相关的拣选历史
|
// 注意:Dt_PickingRecord 中没有直接存储OrderId,需要通过出库单明细关联
|
var detailIds = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
|
.Where(d => d.OrderId == orderId)
|
.Select(d => d.Id)
|
.ToListAsync();
|
|
return await Db.Queryable<Dt_PickingRecord>()
|
.Where(p => detailIds.Contains(p.OrderDetailId))
|
.OrderByDescending(p => p.PickTime)
|
.ToListAsync();
|
}
|
|
public async Task GetPalletPickingSummary(string orderNo, string palletCode)
|
{
|
var summary = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode)
|
.GroupBy(x => new { x.PalletCode, x.Status })
|
.Select(x => new
|
{
|
PalletCode = x.PalletCode,
|
Status = x.Status,
|
TotalAssignQty = SqlFunc.AggregateSum(x.AssignQuantity),
|
TotalPickedQty = SqlFunc.AggregateSum(x.PickedQty)
|
})
|
.ToListAsync();
|
|
// return summary;
|
}
|
|
|
|
/// <summary>
|
/// 撤销拣选
|
/// </summary>
|
public async Task<WebResponseContent> CancelPicking(CancelPickingRequest request)
|
{
|
// 实现撤销拣选的逻辑,需要:
|
// 1. 恢复库存出库数量
|
// 2. 恢复锁定信息的已拣选数量
|
// 3. 恢复出库单明细的已出数量和锁定数量
|
// 4. 删除或标记拣选历史记录
|
// 注意:这里需要事务处理
|
try
|
{
|
_unitOfWorkManage.BeginTran();
|
|
var pickHistory = await Db.Queryable<Dt_PickingRecord>()
|
.Where(x => x.Id == request.PickingHistoryId)
|
.FirstAsync();
|
|
if (pickHistory == null)
|
return WebResponseContent.Instance.Error("未找到拣选记录");
|
|
// 恢复库存
|
var stockDetail = await _stockInfoService.Db.Queryable<Dt_StockInfoDetail>()
|
.Where(x => x.Barcode == pickHistory.Barcode && x.StockId == pickHistory.StockId)
|
.FirstAsync();
|
if (stockDetail != null)
|
{
|
stockDetail.OutboundQuantity -= pickHistory.PickQuantity;
|
await _stockInfoService.Db.Updateable(stockDetail).ExecuteCommandAsync();
|
}
|
// 恢复锁定信息
|
var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.OrderDetailId == pickHistory.OrderDetailId && x.StockId == pickHistory.StockId)
|
.FirstAsync();
|
lockInfo.PickedQty -= pickHistory.PickQuantity;
|
await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
|
|
// 恢复出库单明细
|
var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
|
.Where(x => x.Id == pickHistory.OrderDetailId)
|
.FirstAsync();
|
orderDetail.OverOutQuantity -= pickHistory.PickQuantity;
|
orderDetail.LockQuantity += pickHistory.PickQuantity;
|
if (orderDetail.OverOutQuantity < orderDetail.OrderQuantity)
|
{
|
orderDetail.OrderDetailStatus = orderDetail.LockQuantity > 0 ?
|
(int)OrderDetailStatusEnum.Outbound : (int)OrderDetailStatusEnum.AssignOverPartial;
|
}
|
await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
|
|
// 删除拣选历史记录
|
await Db.Deleteable<Dt_PickingRecord>().Where(x => x.Id == request.PickingHistoryId).ExecuteCommandAsync();
|
|
_unitOfWorkManage.CommitTran();
|
return WebResponseContent.Instance.OK("撤销成功");
|
}
|
catch (Exception ex)
|
{
|
_unitOfWorkManage.RollbackTran();
|
return WebResponseContent.Instance.Error($"撤销失败: {ex.Message}");
|
}
|
}
|
|
/// <summary>
|
/// 获取托盘的出库状态信息
|
/// </summary>
|
public async Task<WebResponseContent> GetPalletOutboundStatus(string palletCode)
|
{
|
// 获取托盘的锁定信息
|
var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.PalletCode == palletCode)
|
.ToListAsync();
|
|
// 获取托盘库存信息
|
var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
|
.Includes(x => x.Details)
|
.Where(x => x.PalletCode == palletCode)
|
.FirstAsync();
|
|
if (stockInfo == null)
|
return WebResponseContent.Instance.Error("未找到托盘信息");
|
|
// 计算各种数量
|
var totalStockQuantity = stockInfo.Details.Sum(x => x.StockQuantity);
|
var totalOutboundQuantity = stockInfo.Details.Sum(x => x.OutboundQuantity);
|
var totalLockedQuantity = lockInfos.Where(x => x.Status == (int)OutLockStockStatusEnum.出库中)
|
.Sum(x => x.AssignQuantity - x.PickedQty);
|
var totalPickedQuantity = lockInfos.Sum(x => x.PickedQty);
|
|
var result = new
|
{
|
PalletCode = palletCode,
|
LocationCode = stockInfo.LocationCode,
|
StockStatus = stockInfo.StockStatus,
|
TotalStockQuantity = totalStockQuantity,
|
TotalOutboundQuantity = totalOutboundQuantity,
|
TotalLockedQuantity = totalLockedQuantity,
|
TotalPickedQuantity = totalPickedQuantity,
|
AvailableQuantity = totalStockQuantity - totalOutboundQuantity,
|
LockInfos = lockInfos.Select(x => new
|
{
|
x.Id,
|
x.MaterielCode,
|
x.OrderDetailId,
|
x.AssignQuantity,
|
x.PickedQty,
|
x.Status,
|
x.CurrentBarcode,
|
x.IsSplitted
|
}).ToList(),
|
StockDetails = stockInfo.Details.Select(x => new
|
{
|
x.Barcode,
|
x.MaterielCode,
|
StockQuantity = x.StockQuantity,
|
OutboundQuantity = x.OutboundQuantity,
|
AvailableQuantity = x.StockQuantity - x.OutboundQuantity
|
}).ToList()
|
};
|
|
return WebResponseContent.Instance.OK(null, result);
|
}
|
|
/// <summary>
|
/// 直接出库 - 整个托盘出库,清空库存
|
/// </summary>
|
public async Task<WebResponseContent> DirectOutbound(DirectOutboundRequest request)
|
{
|
try
|
{
|
_unitOfWorkManage.BeginTran();
|
|
var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
|
.Includes(x => x.Details)
|
.Where(x => x.PalletCode == request.PalletCode).FirstAsync();
|
|
if (stockInfo == null)
|
return WebResponseContent.Instance.Error("未找到托盘库存信息");
|
|
|
var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.OrderNo == request.OrderNo && x.PalletCode == request.PalletCode)
|
.ToListAsync();
|
|
|
foreach (var lockInfo in lockInfos)
|
{
|
if (lockInfo.Status == (int)OutLockStockStatusEnum.出库中)
|
{
|
lockInfo.PickedQty = lockInfo.AssignQuantity;
|
}
|
lockInfo.Status = (int)OutLockStockStatusEnum.已出库;
|
await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
|
|
var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
|
.Where(x => x.Id == lockInfo.OrderDetailId)
|
.FirstAsync();
|
if (orderDetail != null)
|
{
|
orderDetail.OverOutQuantity += lockInfo.PickedQty;
|
orderDetail.LockQuantity -= lockInfo.PickedQty;
|
orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.Over;
|
orderDetail.LockQuantity = 0;
|
await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
|
}
|
}
|
var groupDetails = lockInfos.GroupBy(x => x.OrderDetailId).Select(x => new
|
{
|
OrderDetailId = x.Key,
|
TotalQuantity = x.Sum(o => o.PickedQty)
|
}).ToList();
|
foreach (var item in groupDetails)
|
{
|
var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>().Where(x => x.Id == item.OrderDetailId).FirstAsync();
|
if (orderDetail != null)
|
{
|
orderDetail.OverOutQuantity = item.TotalQuantity;
|
orderDetail.LockQuantity = 0;
|
orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.Over;
|
await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
|
}
|
}
|
|
await CheckAndUpdateOrderStatus(request.OrderNo);
|
|
var lockInfoIds = lockInfos.Select(x => x.Id).ToList();
|
var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
|
.Where(x => lockInfoIds.Contains(x.OutStockLockInfoId) &&
|
x.Status == (int)SplitPackageStatusEnum.已拆包)
|
.ToListAsync();
|
|
foreach (var record in splitRecords)
|
{
|
record.Status = (int)SplitPackageStatusEnum.已拣选;
|
await _splitPackageService.Db.Updateable(record).ExecuteCommandAsync();
|
}
|
|
|
var location = await _locationInfoService.Db.Queryable<Dt_LocationInfo>()
|
.Where(x => x.LocationCode == stockInfo.LocationCode)
|
.FirstAsync();
|
if (location != null)
|
{
|
location.LocationStatus = (int)LocationStatusEnum.Free;
|
await _locationInfoService.Db.Updateable(location).ExecuteCommandAsync();
|
}
|
|
foreach (var detail in stockInfo.Details)
|
{
|
await _stockInfoDetailService.Db.Deleteable(detail).ExecuteCommandAsync();
|
}
|
await _stockInfoService.Db.Deleteable(stockInfo).ExecuteCommandAsync();
|
|
|
|
_unitOfWorkManage.CommitTran();
|
return WebResponseContent.Instance.OK("直接出库成功");
|
}
|
catch (Exception ex)
|
{
|
_unitOfWorkManage.RollbackTran();
|
return WebResponseContent.Instance.Error($"直接出库失败: {ex.Message}");
|
}
|
}
|
}
|
|
}
|