#region << 版 本 注 释 >>
|
/*----------------------------------------------------------------
|
* 命名空间:WIDESEA_TaskInfoService
|
* 创建者:胡童庆
|
* 创建时间:2024/8/2 16:13:36
|
* 版本:V1.0.0
|
* 描述:
|
*
|
* ----------------------------------------------------------------
|
* 修改人:
|
* 修改时间:
|
* 版本:V1.0.1
|
* 修改说明:
|
*
|
*----------------------------------------------------------------*/
|
#endregion << 版 本 注 释 >>
|
|
using AutoMapper;
|
using Dm.filter;
|
using MailKit.Search;
|
using Microsoft.Extensions.Logging;
|
using Newtonsoft.Json;
|
using Org.BouncyCastle.Asn1.Ocsp;
|
using Org.BouncyCastle.Asn1.Pkcs;
|
using SqlSugar;
|
using System.Reflection;
|
using System.Reflection.Emit;
|
using System.Threading.Tasks;
|
using System.Xml.Linq;
|
using WIDESEA_BasicService;
|
using WIDESEA_Common.AllocateEnum;
|
using WIDESEA_Common.CommonEnum;
|
using WIDESEA_Common.LocationEnum;
|
using WIDESEA_Common.OrderEnum;
|
using WIDESEA_Common.StockEnum;
|
using WIDESEA_Common.TaskEnum;
|
using WIDESEA_Common.WareHouseEnum;
|
using WIDESEA_Core;
|
using WIDESEA_Core.BaseRepository;
|
using WIDESEA_Core.BaseServices;
|
using WIDESEA_Core.Enums;
|
using WIDESEA_Core.Helper;
|
using WIDESEA_DTO.Allocate;
|
using WIDESEA_DTO.Basic;
|
using WIDESEA_DTO.Inbound;
|
using WIDESEA_DTO.Outbound;
|
using WIDESEA_DTO.Task;
|
using WIDESEA_IAllocateService;
|
using WIDESEA_IBasicService;
|
using WIDESEA_IInboundService;
|
using WIDESEA_IOutboundService;
|
using WIDESEA_IRecordService;
|
using WIDESEA_IStockService;
|
using WIDESEA_ITaskInfoService;
|
using WIDESEA_Model.Models;
|
using WIDESEA_Model.Models.Check;
|
using WIDESEA_Model.Models.Outbound;
|
|
namespace WIDESEA_TaskInfoService
|
{
|
public partial class TaskService : ServiceBase<Dt_Task, IRepository<Dt_Task>>, ITaskService
|
{
|
private readonly ILogger<TaskService> _logger;
|
private readonly IMapper _mapper;
|
private readonly IUnitOfWorkManage _unitOfWorkManage;
|
|
private readonly IRepository<Dt_StockInfo> _stockRepository;
|
private readonly ILocationInfoService _locationInfoService;
|
private readonly IInboundOrderService _inboundOrderService;
|
private readonly IInboundOrderDetailService _inboundOrderDetailService;
|
|
private readonly IRepository<Dt_AllocateOrderDetail> _allocateOrderDetailRepository;
|
private readonly IRepository<Dt_AllocateOrder> _allocateOrderRepository;
|
private readonly IRepository<Dt_ReCheckOrder> _reCheckOrderRepository;
|
private readonly IRepository<Dt_OutboundBatch> _OutboundBatchRepository;
|
private readonly IOutboundOrderService _outboundOrderService;
|
private readonly IOutboundOrderDetailService _outboundOrderDetailService;
|
private readonly IOutStockLockInfoService _outStockLockInfoService;
|
private readonly ILocationStatusChangeRecordService _locationStatusChangeRecordService;
|
private readonly IMaterialUnitService _materialUnitService;
|
private readonly IESSApiService _eSSApiService;
|
private readonly IStockService _stockService;
|
private readonly IRecordService _recordService;
|
private readonly IAllocateService _allocateService;
|
private readonly IInvokeMESService _invokeMESService;
|
public IRepository<Dt_Task> Repository => BaseDal;
|
|
private Dictionary<string, SqlSugar.OrderByType> _taskOrderBy = new()
|
{
|
{nameof(Dt_Task.Grade),SqlSugar.OrderByType.Desc },
|
{nameof(Dt_Task.CreateDate),SqlSugar.OrderByType.Asc},
|
};
|
|
private Dictionary<string, string> stations = new Dictionary<string, string>
|
{
|
{"3-5","3-9" },
|
{"2-5","2-9" },
|
{"1-11","1-1" },
|
};
|
|
public List<int> TaskTypes => typeof(TaskTypeEnum).GetEnumIndexList();
|
|
public List<int> TaskOutboundTypes => typeof(TaskTypeEnum).GetEnumIndexList();
|
|
public TaskService(IRepository<Dt_Task> BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_StockInfo> stockRepository, ILocationInfoService locationInfoService, IInboundOrderService inboundOrderService, ILocationStatusChangeRecordService locationStatusChangeRecordService, IESSApiService eSSApiService, ILogger<TaskService> logger, IStockService stockService, IRecordService recordService, IInboundOrderDetailService inboundOrderDetailService, IOutboundOrderService outboundOrderService, IOutboundOrderDetailService outboundOrderDetailService, IInvokeMESService invokeMESService, IOutStockLockInfoService outStockLockInfoService, IAllocateService allocateService, IRepository<Dt_OutboundBatch> outboundBatchRepository, IRepository<Dt_ReCheckOrder> reCheckOrderRepository, IRepository<Dt_AllocateOrderDetail> allocateOrderDetailRepository, IRepository<Dt_AllocateOrder> allocateOrderRepository, IMaterialUnitService materialUnitService) : base(BaseDal)
|
{
|
_mapper = mapper;
|
_unitOfWorkManage = unitOfWorkManage;
|
_stockRepository = stockRepository;
|
_locationInfoService = locationInfoService;
|
_inboundOrderService = inboundOrderService;
|
_locationStatusChangeRecordService = locationStatusChangeRecordService;
|
_eSSApiService = eSSApiService;
|
_logger = logger;
|
_stockService = stockService;
|
_recordService = recordService;
|
_inboundOrderDetailService = inboundOrderDetailService;
|
_outboundOrderService = outboundOrderService;
|
_outboundOrderDetailService = outboundOrderDetailService;
|
_invokeMESService = invokeMESService;
|
_outStockLockInfoService = outStockLockInfoService;
|
_allocateService = allocateService;
|
_OutboundBatchRepository = outboundBatchRepository;
|
_reCheckOrderRepository = reCheckOrderRepository;
|
_allocateOrderDetailRepository = allocateOrderDetailRepository;
|
_allocateOrderRepository = allocateOrderRepository;
|
_materialUnitService = materialUnitService;
|
}
|
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="taskNum"></param>
|
/// <returns></returns>
|
public async Task<WebResponseContent> TaskCompleted(string taskNum)
|
{
|
try
|
{
|
Dt_Task task;
|
|
if (int.TryParse(taskNum, out var newTaskNum))
|
{
|
task = await BaseDal.QueryFirstAsync(x => x.TaskNum == newTaskNum);
|
if (task == null)
|
{
|
return WebResponseContent.Instance.Error("未找到任务信息");
|
}
|
}
|
else
|
{
|
return WebResponseContent.Instance.Error("未找到任务信息");
|
}
|
_logger.LogInformation($"TaskService TaskCompleted: {JsonConvert.SerializeObject(task)} , {task.TaskType} ");
|
|
MethodInfo? methodInfo = GetType().GetMethod(((TaskTypeEnum)task.TaskType) + "TaskCompleted");
|
if (methodInfo != null)
|
{
|
object? taskResult = methodInfo.Invoke(this, new object[] { task });
|
if (taskResult is Task<WebResponseContent> asyncTask)
|
{
|
try
|
{
|
// 3. 异步等待 Task 完成,自动解析出 WebResponseContent
|
WebResponseContent responseContent = await asyncTask;
|
if (responseContent != null)
|
{
|
return responseContent;
|
}
|
}
|
catch (AggregateException ex)
|
{
|
_logger.LogError($"TaskService TaskCompleted taskResult: {ex.Message} ");
|
return WebResponseContent.Instance.Error(ex.Message);
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError(ex, $"Unexpected error in {task.TaskType}");
|
return WebResponseContent.Instance.Error(ex.Message);
|
}
|
}
|
}
|
return WebResponseContent.Instance.Error("未找到任务类型对应业务处理逻辑");
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError($"TaskService TaskCompleted: {ex.Message} ");
|
return WebResponseContent.Instance.Error(ex.Message);
|
}
|
}
|
/// <summary>
|
/// 入库完成
|
/// </summary>
|
/// <param name="task"></param>
|
/// <returns></returns>
|
public async Task<WebResponseContent> InboundTaskCompleted(Dt_Task task)
|
{
|
decimal beforeQuantity = 0;
|
|
//查库存
|
Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Includes(x => x.Details).Where(x => x.PalletCode == task.PalletCode && x.WarehouseId == task.WarehouseId).First();
|
if (stockInfo == null)
|
{
|
return WebResponseContent.Instance.Error($"未找到托盘对应的组盘信息");
|
}
|
if (stockInfo.Details.Count == 0 && stockInfo.PalletType != PalletTypeEnum.Empty.ObjToInt())
|
{
|
return WebResponseContent.Instance.Error($"未找到该托盘库存明细信息");
|
}
|
//查货位
|
Dt_LocationInfo locationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == task.TargetAddress);
|
if (locationInfo == null)
|
{
|
return WebResponseContent.Instance.Error($"未找到对应的终点货位信息");
|
}
|
|
var ordernos = stockInfo.Details.GroupBy(x => x.OrderNo).Select(o => o.Key).ToList();
|
var inboundOrders = _inboundOrderService.Repository.Db.Queryable<Dt_InboundOrder>().Where(x => ordernos.Contains(x.InboundOrderNo)).Includes(x => x.Details).ToList();
|
Dt_InboundOrderDetail? inboundOrderDetail = null;
|
|
foreach (var inboundOrder in inboundOrders)
|
{
|
//标准入库流程查找入库单据
|
if (inboundOrder != null && stockInfo.StockStatus == StockStatusEmun.入库确认.ObjToInt())
|
{
|
foreach (var item in stockInfo.Details.Where(x => x.OrderNo == inboundOrder.InboundOrderNo).ToList())
|
{
|
var inbounddetail = inboundOrder.Details.Where(x => x.lineNo == item.InboundOrderRowNo && x.Barcode == item.Barcode).FirstOrDefault();
|
if (inbounddetail != null)
|
{
|
inbounddetail.OverInQuantity += item.StockQuantity;
|
if (inbounddetail.OverInQuantity == inbounddetail.OrderQuantity)
|
{
|
inbounddetail.OrderDetailStatus = OrderDetailStatusEnum.Over.ObjToInt();
|
}
|
else if (inbounddetail.OrderDetailStatus == OrderDetailStatusEnum.New.ObjToInt())
|
{
|
inbounddetail.OrderDetailStatus = OrderDetailStatusEnum.Inbounding.ObjToInt();
|
}
|
_inboundOrderDetailService.UpdateData(inbounddetail);
|
}
|
}
|
if (inboundOrder.Details.Count == inboundOrder.Details.Where(x => x.OrderQuantity == x.OverInQuantity).Count())
|
{
|
inboundOrder.OrderStatus = InOrderStatusEnum.入库完成.ObjToInt();
|
}
|
else if (inboundOrder.OrderStatus == InOrderStatusEnum.未开始.ObjToInt())
|
{
|
inboundOrder.OrderStatus = InOrderStatusEnum.入库中.ObjToInt();
|
}
|
_inboundOrderService.UpdateData(inboundOrder);
|
}
|
}
|
stockInfo.LocationCode = task.TargetAddress;
|
stockInfo.StockStatus = StockStatusEmun.入库完成.ObjToInt();
|
stockInfo.Details.ForEach(x =>
|
{
|
x.Status = StockStatusEmun.入库完成.ObjToInt();
|
});
|
_stockService.StockInfoService.Repository.UpdateData(stockInfo);
|
_stockService.StockInfoDetailService.Repository.UpdateData(stockInfo.Details);
|
|
beforeQuantity = stockInfo.Details.Where(x => x.Id != 0).Sum(x => x.StockQuantity);
|
|
int beforeStatus = locationInfo.LocationStatus;
|
if (stockInfo.PalletType == PalletTypeEnum.Empty.ObjToInt())
|
{
|
locationInfo.LocationStatus = LocationStatusEnum.Pallet.ObjToInt();
|
}
|
else
|
{
|
locationInfo.LocationStatus = LocationStatusEnum.InStock.ObjToInt();
|
}
|
_locationInfoService.Repository.UpdateData(locationInfo);
|
|
task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
|
|
BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
|
|
_locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Inbound.ObjToInt(), "", task.TaskNum);
|
|
_recordService.StockQuantityChangeRecordService.AddStockChangeRecord(stockInfo, stockInfo.Details, beforeQuantity, stockInfo.Details.Sum(x => x.StockQuantity) + beforeQuantity, WIDESEA_Common.StockEnum.StockChangeType.MaterielGroup);
|
try
|
{
|
foreach (var inboundOrder in inboundOrders)
|
{
|
if (inboundOrder.OrderType == InOrderTypeEnum.AllocatInbound.ObjToInt())//调拨入库
|
{
|
if (inboundOrder != null && inboundOrder.OrderStatus == InOrderStatusEnum.入库完成.ObjToInt())
|
{
|
var allocate = _allocateService.Repository.QueryData(x => x.OrderNo == inboundOrder.InboundOrderNo).First();
|
var allocatefeedmodel = new AllocateDto
|
{
|
ReqCode = Guid.NewGuid().ToString(),
|
ReqTime = DateTime.Now.ToString(),
|
BusinessType = BusinessTypeEnum.外部仓库调智仓.ObjToInt().ToString(),
|
FactoryArea = inboundOrder.FactoryArea,
|
OperationType = 1,
|
Operator = inboundOrder.Operator,
|
OrderNo = inboundOrder.UpperOrderNo,
|
fromWarehouse = allocate?.FromWarehouse ?? "",
|
toWarehouse = allocate?.ToWarehouse ?? "",
|
Details = new List<AllocateDtoDetail>()
|
|
};
|
|
var groupedData = inboundOrder.Details.GroupBy(item => new { item.MaterielCode, item.lineNo, item.BarcodeUnit, item.WarehouseCode })
|
.Select(group => new AllocateDtoDetail
|
{
|
MaterialCode = group.Key.MaterielCode,
|
LineNo = group.Key.lineNo,
|
WarehouseCode = group.Key.WarehouseCode,
|
Qty = group.Sum(x => x.BarcodeQty),
|
// warehouseCode= "1072",
|
Unit = group.Key.BarcodeUnit,
|
Barcodes = group.Select(row => new BarcodeInfo
|
{
|
Barcode = row.Barcode,
|
Qty = row.BarcodeQty,
|
BatchNo = row.BatchNo,
|
SupplyCode = row.SupplyCode,
|
Unit = row.BarcodeUnit
|
}).ToList()
|
}).ToList();
|
allocatefeedmodel.Details = groupedData;
|
|
var result = await _invokeMESService.FeedbackAllocate(allocatefeedmodel);
|
if (result != null && result.code == 200)
|
{
|
_inboundOrderService.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus = 1 })
|
.Where(it => it.Id == inboundOrder.Id).ExecuteCommand();
|
_inboundOrderDetailService.Db.Updateable<Dt_InboundOrderDetail>().SetColumns(it => new Dt_InboundOrderDetail { ReturnToMESStatus = 1 })
|
.Where(it => it.OrderId == inboundOrder.Id).ExecuteCommand();
|
}
|
}
|
}
|
else if (inboundOrder.OrderType == InOrderTypeEnum.ReCheck.ObjToInt()) //重检入库
|
{
|
//不需要回传。占一个位置。
|
}
|
else if (inboundOrder.OrderType == InOrderTypeEnum.InternalAllocat.ObjToInt()) //智仓调智仓
|
{
|
_logger.LogInformation($"InboundTaskCompleted 回写MES : {inboundOrder.InboundOrderNo} ,ordertype: {InOrderTypeEnum.InternalAllocat.ObjToInt()} ");
|
// BusinessTypeEnum.智仓调智仓
|
if (inboundOrder != null && inboundOrder.OrderStatus == InOrderStatusEnum.入库完成.ObjToInt())
|
{
|
var allocate = _allocateService.Repository.QueryData(x => x.OrderNo == inboundOrder.InboundOrderNo).First();
|
var allocatefeedmodel = new AllocateDto
|
{
|
ReqCode = Guid.NewGuid().ToString(),
|
ReqTime = DateTime.Now.ToString(),
|
BusinessType = BusinessTypeEnum.智仓调智仓.ObjToInt().ToString(),
|
FactoryArea = inboundOrder.FactoryArea,
|
OperationType = 1,
|
Operator = inboundOrder.Operator,
|
OrderNo = inboundOrder.UpperOrderNo,
|
fromWarehouse = allocate?.FromWarehouse ?? "",
|
toWarehouse = allocate?.ToWarehouse ?? "",
|
Details = new List<AllocateDtoDetail>()
|
|
};
|
|
var groupedData = inboundOrder.Details.GroupBy(item => new { item.MaterielCode, item.lineNo, item.BarcodeUnit, item.WarehouseCode })
|
.Select(group => new AllocateDtoDetail
|
{
|
MaterialCode = group.Key.MaterielCode,
|
LineNo = group.Key.lineNo,
|
WarehouseCode = group.Key.WarehouseCode,
|
Qty = group.Sum(x => x.BarcodeQty),
|
// warehouseCode= "1072",
|
Unit = group.Key.BarcodeUnit,
|
Barcodes = group.Select(row => new BarcodeInfo
|
{
|
Barcode = row.Barcode,
|
Qty = row.BarcodeQty,
|
BatchNo = row.BatchNo,
|
SupplyCode = row.SupplyCode,
|
Unit = row.BarcodeUnit
|
}).ToList()
|
}).ToList();
|
allocatefeedmodel.Details = groupedData;
|
|
var result = await _invokeMESService.FeedbackAllocate(allocatefeedmodel);
|
if (result != null && result.code == 200)
|
{
|
_inboundOrderService.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus = 1 })
|
.Where(it => it.Id == inboundOrder.Id).ExecuteCommand();
|
_inboundOrderDetailService.Db.Updateable<Dt_InboundOrderDetail>().SetColumns(it => new Dt_InboundOrderDetail { ReturnToMESStatus = 1 })
|
.Where(it => it.OrderId == inboundOrder.Id).ExecuteCommand();
|
}
|
}
|
|
}
|
else
|
{
|
if (inboundOrder != null && inboundOrder.OrderStatus == InOrderStatusEnum.入库完成.ObjToInt())
|
{
|
var feedmodel = new FeedbackInboundRequestModel
|
{
|
reqCode = Guid.NewGuid().ToString(),
|
reqTime = DateTime.Now.ToString(),
|
business_type = inboundOrder.BusinessType,
|
factoryArea = inboundOrder.FactoryArea,
|
operationType = 1,
|
Operator = inboundOrder.Operator,
|
orderNo = inboundOrder.UpperOrderNo,
|
status = inboundOrder.OrderStatus,
|
details = new List<FeedbackInboundDetailsModel>()
|
|
};
|
|
var groupedData = inboundOrder.Details.GroupBy(item => new { item.MaterielCode, item.SupplyCode, item.BatchNo, item.lineNo, item.BarcodeUnit, item.WarehouseCode })
|
.Select(group => new FeedbackInboundDetailsModel
|
{
|
materialCode = group.Key.MaterielCode,
|
supplyCode = group.Key.SupplyCode,
|
batchNo = group.Key.BatchNo,
|
lineNo = group.Key.lineNo,
|
warehouseCode = group.Key.WarehouseCode,
|
qty = group.Sum(x => x.BarcodeQty),
|
// warehouseCode= "1072",
|
unit = group.Key.BarcodeUnit,
|
barcodes = group.Select(row => new FeedbackBarcodesModel
|
{
|
barcode = row.Barcode,
|
qty = row.BarcodeQty
|
}).ToList()
|
}).ToList();
|
feedmodel.details = groupedData;
|
|
var result = await _invokeMESService.FeedbackInbound(feedmodel);
|
if (result != null && result.code == 200)
|
{
|
_inboundOrderService.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus = 1 })
|
.Where(it => it.Id == inboundOrder.Id).ExecuteCommand();
|
_inboundOrderDetailService.Db.Updateable<Dt_InboundOrderDetail>().SetColumns(it => new Dt_InboundOrderDetail { ReturnToMESStatus = 1 })
|
.Where(it => it.OrderId == inboundOrder.Id).ExecuteCommand();
|
}
|
}
|
}
|
|
}
|
}
|
catch (Exception ex)
|
{
|
_logger.LogInformation("InboundTaskCompleted 回写MES失败: " + ex.Message);
|
}
|
|
return WebResponseContent.Instance.OK();
|
}
|
|
|
public async Task<WebResponseContent> OutAllocateTaskCompleted(Dt_Task task)
|
{
|
_logger.LogInformation($"TaskService OutAllocateTaskCompleted: {task.TaskNum}");
|
|
return await OutboundTaskCompleted(task);
|
}
|
public async Task<WebResponseContent> OutboundTaskCompleted(Dt_Task task)
|
{
|
_logger.LogInformation($"TaskService OutboundTaskCompleted: {task.TaskNum}");
|
//查货位
|
Dt_LocationInfo locationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == task.SourceAddress);
|
if (locationInfo == null)
|
{
|
return WebResponseContent.Instance.Error($"未找到对应的终点货位信息");
|
}
|
locationInfo.LocationStatus = LocationStatusEnum.Free.ObjToInt();
|
_locationInfoService.Repository.UpdateData(locationInfo);
|
|
var outloks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>().Where(x => x.TaskNum == task.TaskNum).ToListAsync();
|
|
var stockids = outloks.Select(x => x.StockId).ToList();
|
|
_stockService.StockInfoService.Db.Updateable<Dt_StockInfo>()
|
.SetColumns(it => new Dt_StockInfo
|
{
|
StockStatus = StockStatusEmun.出库锁定.ObjToInt()
|
})
|
.Where(it => stockids.Contains(it.Id))
|
.ExecuteCommand();
|
|
_stockService.StockInfoDetailService.Db.Updateable<Dt_StockInfoDetail>()
|
.SetColumns(it => new Dt_StockInfoDetail
|
{
|
Status = StockStatusEmun.出库锁定.ObjToInt()
|
})
|
.Where(it => stockids.Contains(it.StockId))
|
.ExecuteCommand();
|
|
|
|
return WebResponseContent.Instance.OK();
|
|
|
}
|
public async Task<WebResponseContent> InEmptyTaskCompleted(Dt_Task task)
|
{
|
|
WebResponseContent content = new WebResponseContent();
|
try
|
{
|
|
Dt_LocationInfo locationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == task.TargetAddress);
|
if (locationInfo == null)
|
{
|
return content.Error($"未找到对应的终点货位信息");
|
}
|
Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == task.PalletCode && x.WarehouseId == task.WarehouseId).First();
|
if (stockInfo == null)
|
{
|
return WebResponseContent.Instance.Error($"未找到托盘对应的组盘信息");
|
}
|
|
if (!string.IsNullOrEmpty(stockInfo.LocationCode))
|
{
|
return WebResponseContent.Instance.Error($"该托盘已绑定货位");
|
}
|
if (locationInfo.LocationStatus == LocationStatusEnum.InStock.ObjToInt())
|
{
|
return WebResponseContent.Instance.Error($"货位状态不正确");
|
}
|
|
|
var beforelocationStatus = locationInfo.LocationStatus;
|
locationInfo.LocationStatus = LocationStatusEnum.Pallet.ObjToInt();
|
_locationInfoService.Repository.UpdateData(locationInfo);
|
|
stockInfo.LocationCode = locationInfo.LocationCode;
|
stockInfo.PalletCode = task.PalletCode;
|
stockInfo.LocationCode = task.TargetAddress;
|
stockInfo.StockStatus = StockStatusEmun.入库完成.ObjToInt();
|
_stockRepository.UpdateData(stockInfo);
|
|
var outboundOrder = _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().First(x => x.OrderNo == task.OrderNo);
|
|
task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
|
BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? WIDESEA_Core.Enums.OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
|
|
_locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforelocationStatus, StockChangeType.Inbound.ObjToInt(), "", task.TaskNum);
|
|
|
if (outboundOrder != null)
|
{
|
await HandleOutboundOrderToMESCompletion(outboundOrder, outboundOrder.OrderNo);
|
}
|
else
|
{
|
_logger.LogInformation($"TaskService InEmptyTaskCompleted: {task.TaskNum} ,未找到出库单。 ");
|
}
|
|
return content;
|
}
|
catch (Exception ex)
|
{
|
return await Task.FromResult(WebResponseContent.Instance.Error(ex.Message));
|
}
|
}
|
|
|
public async Task<WebResponseContent> InPickTaskCompleted(Dt_Task task)
|
{
|
_logger.LogInformation($"TaskService InPickTaskCompleted: {task.TaskNum}");
|
|
try
|
{
|
_unitOfWorkManage.BeginTran(); // 添加事务管理
|
|
// 查库存
|
Dt_StockInfo stockInfo = await _stockRepository.Db.Queryable<Dt_StockInfo>()
|
.Includes(x => x.Details)
|
.Where(x => x.PalletCode == task.PalletCode)
|
.FirstAsync();
|
|
if (stockInfo == null)
|
{
|
_logger.LogInformation($"TaskService InPickTaskCompleted: 未找到托盘对应的组盘信息.{task.TaskNum}");
|
return WebResponseContent.Instance.Error($"未找到托盘对应的组盘信息");
|
}
|
|
if (stockInfo.Details.Count == 0 && stockInfo.PalletType != PalletTypeEnum.Empty.ObjToInt())
|
{
|
_logger.LogInformation($"TaskService InPickTaskCompleted: 未找到该托盘库存明细信息.{task.TaskNum}");
|
return WebResponseContent.Instance.Error($"未找到该托盘库存明细信息");
|
}
|
|
// 查货位
|
Dt_LocationInfo locationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == task.TargetAddress);
|
if (locationInfo == null)
|
{
|
_logger.LogInformation($"TaskService InPickTaskCompleted: 未找到对应的终点货位信息 {task.TaskNum}.");
|
return WebResponseContent.Instance.Error($"未找到对应的终点货位信息");
|
}
|
|
var beforelocationStatus = locationInfo.LocationStatus;
|
|
// 获取所有回库中的出库锁定记录
|
var returnLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(it => it.OrderNo == task.OrderNo &&
|
it.PalletCode == task.PalletCode &&
|
it.Status == (int)OutLockStockStatusEnum.回库中)
|
.ToListAsync();
|
|
// 更新出库锁定记录状态为回库完成
|
foreach (var lockInfo in returnLocks)
|
{
|
lockInfo.Status = (int)OutLockStockStatusEnum.已回库;
|
lockInfo.Operator = App.User.UserName;
|
}
|
|
if (returnLocks.Any())
|
{
|
await _outStockLockInfoService.Db.Updateable(returnLocks).ExecuteCommandAsync();
|
_logger.LogInformation($"更新{returnLocks.Count}条锁定记录为已回库状态");
|
}
|
|
// 更新库存信息
|
stockInfo.LocationCode = task.TargetAddress;
|
stockInfo.StockStatus = StockStatusEmun.入库完成.ObjToInt();
|
|
// 更新库存明细状态
|
if (stockInfo.Details != null && stockInfo.Details.Any())
|
{
|
foreach (var detail in stockInfo.Details)
|
{
|
detail.Status = StockStatusEmun.入库完成.ObjToInt();
|
detail.OutboundQuantity = 0; // 入库完成时出库数量清零
|
}
|
_stockService.StockInfoDetailService.Repository.UpdateData(stockInfo.Details);
|
}
|
|
_stockService.StockInfoService.Repository.UpdateData(stockInfo);
|
// 删除零库存数据
|
await DeleteZeroQuantityStockDetails(stockInfo.Id);
|
|
await UpdateAffectedOrderDetails(task.OrderNo, returnLocks);
|
// 更新货位状态
|
if (stockInfo.PalletType == PalletTypeEnum.Empty.ObjToInt())
|
{
|
locationInfo.LocationStatus = LocationStatusEnum.Pallet.ObjToInt();
|
}
|
else
|
{
|
locationInfo.LocationStatus = LocationStatusEnum.InStock.ObjToInt();
|
}
|
|
_locationInfoService.Repository.UpdateData(locationInfo);
|
|
task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
|
|
// 删除任务记录
|
BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
|
BaseDal.DeleteData(task);
|
|
// 记录货位状态变更
|
_locationStatusChangeRecordService.AddLocationStatusChangeRecord(
|
locationInfo,
|
beforelocationStatus,
|
StockChangeType.Inbound.ObjToInt(),
|
"",
|
task.TaskNum
|
);
|
await RecalculateOrderStatus(task.OrderNo);
|
|
_unitOfWorkManage.CommitTran(); // 提交事务
|
_logger.LogInformation($"托盘回库完成处理成功 - 任务号: {task.TaskNum}, 托盘: {task.PalletCode}, 订单: {task.OrderNo}");
|
_ = Task.Run(async () =>
|
{
|
try
|
{
|
var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
|
.FirstAsync(x => x.OrderNo == task.OrderNo);
|
|
if (outboundOrder != null)
|
{
|
// 检查订单是否已完成,只有完成时才向MES反馈
|
if (outboundOrder.OrderStatus == (int)OutOrderStatusEnum.出库完成)
|
{
|
await HandleOutboundOrderToMESCompletion(outboundOrder, outboundOrder.OrderNo);
|
}
|
else
|
{
|
_logger.LogInformation($"订单{task.OrderNo}状态为{outboundOrder.OrderStatus},暂不向MES反馈");
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError($"异步MES反馈处理失败 - OrderNo: {task.OrderNo}, Error: {ex.Message}");
|
}
|
});
|
}
|
catch (Exception ex)
|
{
|
_unitOfWorkManage.RollbackTran(); // 回滚事务
|
_logger.LogError($"TaskService InPickTaskCompleted失败 - TaskNum: {task.TaskNum}, Error: {ex.Message}");
|
return WebResponseContent.Instance.Error($"回库任务完成处理失败: {ex.Message}");
|
}
|
|
return WebResponseContent.Instance.OK();
|
}
|
// <summary>
|
/// 更新受影响的订单明细锁定数量
|
/// </summary>
|
private async Task UpdateAffectedOrderDetails(string orderNo, List<Dt_OutStockLockInfo> returnLocks)
|
{
|
try
|
{
|
// 获取受影响的订单明细ID(去重)
|
var affectedDetailIds = returnLocks
|
.Select(x => x.OrderDetailId)
|
.Distinct()
|
.ToList();
|
|
if (!affectedDetailIds.Any())
|
{
|
_logger.LogInformation($"没有受影响的订单明细 - OrderNo: {orderNo}");
|
return;
|
}
|
|
_logger.LogInformation($"更新{affectedDetailIds.Count}个受影响的订单明细 - OrderNo: {orderNo}");
|
|
foreach (var detailId in affectedDetailIds)
|
{
|
// 重新计算该订单明细的锁定数量
|
decimal currentLockQty = await CalculateOrderDetailLockQuantity(detailId);
|
|
// 检查数据一致性
|
if (currentLockQty < 0)
|
{
|
_logger.LogWarning($"锁定数量计算为负值 - OrderDetailId: {detailId}, 当前值: {currentLockQty},重置为0");
|
currentLockQty = 0;
|
}
|
|
// 获取订单明细
|
var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
|
.FirstAsync(x => x.Id == detailId);
|
|
if (orderDetail == null)
|
{
|
_logger.LogWarning($"未找到订单明细 - OrderDetailId: {detailId}");
|
continue;
|
}
|
|
// 更新锁定数量
|
if (orderDetail.LockQuantity != currentLockQty)
|
{
|
await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
|
.SetColumns(it => new Dt_OutboundOrderDetail
|
{
|
LockQuantity = currentLockQty,
|
})
|
.Where(it => it.Id == detailId)
|
.ExecuteCommandAsync();
|
|
_logger.LogInformation($"更新订单明细锁定数量 - OrderDetailId: {detailId}, " +
|
$"旧值: {orderDetail.LockQuantity}, 新值: {currentLockQty}");
|
}
|
|
// 更新订单明细状态
|
await UpdateOrderDetailStatus(orderDetail);
|
}
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError($"UpdateAffectedOrderDetails失败 - OrderNo: {orderNo}, Error: {ex.Message}");
|
throw;
|
}
|
}
|
|
/// <summary>
|
/// 重新计算订单明细锁定数量
|
/// </summary>
|
private async Task<decimal> CalculateOrderDetailLockQuantity(int orderDetailId)
|
{
|
try
|
{
|
// 查找该订单明细下所有状态为"出库中"的锁定记录
|
var activeLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.OrderDetailId == orderDetailId &&
|
x.Status == (int)OutLockStockStatusEnum.出库中)
|
.ToListAsync();
|
|
// 过滤拆包记录
|
var filteredLocks = new List<Dt_OutStockLockInfo>();
|
|
foreach (var lockInfo in activeLocks)
|
{
|
// 如果是拆包记录,需要特殊处理
|
if (lockInfo.IsSplitted == 1 && lockInfo.ParentLockId.HasValue)
|
{
|
// 查找父锁定记录
|
var parentLock = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.Id == lockInfo.ParentLockId.Value)
|
.FirstAsync();
|
|
// 如果父记录存在且状态也是出库中,则只计算父记录
|
if (parentLock != null && parentLock.Status == (int)OutLockStockStatusEnum.出库中)
|
{
|
// 父记录已经在列表中,跳过当前拆包记录
|
continue;
|
}
|
}
|
|
filteredLocks.Add(lockInfo);
|
}
|
|
decimal totalLockQty = filteredLocks.Sum(x => x.AssignQuantity - x.PickedQty);
|
|
_logger.LogDebug($"计算锁定数量 - OrderDetailId: {orderDetailId}, " +
|
$"找到{filteredLocks.Count}个有效锁定记录, " +
|
$"总锁定数量: {totalLockQty}");
|
|
return totalLockQty;
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError($"CalculateOrderDetailLockQuantity失败 - OrderDetailId: {orderDetailId}, Error: {ex.Message}");
|
return 0;
|
}
|
}
|
|
/// <summary>
|
/// 更新订单明细状态
|
/// </summary>
|
private async Task UpdateOrderDetailStatus(Dt_OutboundOrderDetail orderDetail)
|
{
|
try
|
{
|
int newStatus = orderDetail.OrderDetailStatus;
|
|
// 根据实际枚举值调整
|
// 检查是否已完成(已出库数量 >= 需求数量)
|
if (orderDetail.OverOutQuantity >= orderDetail.NeedOutQuantity)
|
{
|
newStatus = (int)OrderDetailStatusEnum.Over; // 已完成
|
}
|
// 检查是否有部分出库或有锁定数量
|
else if (orderDetail.OverOutQuantity > 0 || orderDetail.LockQuantity > 0)
|
{
|
newStatus = (int)OrderDetailStatusEnum.Outbound; // 部分完成/进行中
|
}
|
// 否则为新订单
|
else
|
{
|
newStatus = (int)OrderDetailStatusEnum.New; // 新建
|
}
|
|
// 只有状态变化时才更新
|
if (orderDetail.OrderDetailStatus != newStatus)
|
{
|
await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
|
.SetColumns(it => new Dt_OutboundOrderDetail
|
{
|
OrderDetailStatus = newStatus,
|
})
|
.Where(it => it.Id == orderDetail.Id)
|
.ExecuteCommandAsync();
|
|
_logger.LogInformation($"更新订单明细状态 - OrderDetailId: {orderDetail.Id}, " +
|
$"旧状态: {orderDetail.OrderDetailStatus}, 新状态: {newStatus}, " +
|
$"已出库: {orderDetail.OverOutQuantity}/{orderDetail.NeedOutQuantity}, " +
|
$"锁定数量: {orderDetail.LockQuantity}");
|
}
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError($"UpdateOrderDetailStatus失败 - OrderDetailId: {orderDetail.Id}, Error: {ex.Message}");
|
throw;
|
}
|
}
|
|
/// <summary>
|
/// 重新计算并更新订单状态
|
/// </summary>
|
private async Task RecalculateOrderStatus(string orderNo)
|
{
|
try
|
{
|
// 获取订单的所有明细
|
var orderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
|
.LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id)
|
.Where((o, item) => item.OrderNo == orderNo)
|
.Select((o, item) => o)
|
.ToListAsync();
|
|
if (!orderDetails.Any())
|
{
|
_logger.LogWarning($"未找到订单明细 - OrderNo: {orderNo}");
|
return;
|
}
|
|
// 检查状态
|
bool allCompleted = true;
|
bool hasInProgress = false;
|
|
foreach (var detail in orderDetails)
|
{
|
// 检查是否完成
|
if (detail.OverOutQuantity < detail.NeedOutQuantity)
|
{
|
allCompleted = false;
|
}
|
|
// 检查是否有进行中的任务(锁定或部分拣选)
|
if (detail.LockQuantity > 0 ||
|
detail.OrderDetailStatus == (int)OrderDetailStatusEnum.Outbound)
|
{
|
hasInProgress = true;
|
}
|
}
|
|
var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
|
.FirstAsync(x => x.OrderNo == orderNo);
|
|
if (outboundOrder == null)
|
{
|
_logger.LogWarning($"未找到出库订单 - OrderNo: {orderNo}");
|
return;
|
}
|
|
int newStatus;
|
if (allCompleted)
|
{
|
newStatus = (int)OutOrderStatusEnum.出库完成;
|
}
|
else if (hasInProgress)
|
{
|
newStatus = (int)OutOrderStatusEnum.出库中;
|
}
|
else
|
{
|
newStatus = (int)OutOrderStatusEnum.未开始;
|
}
|
|
if (outboundOrder.OrderStatus != newStatus)
|
{
|
await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
|
.SetColumns(x => new Dt_OutboundOrder
|
{
|
OrderStatus = newStatus,
|
Operator = App.User.UserName,
|
})
|
.Where(x => x.OrderNo == orderNo)
|
.ExecuteCommandAsync();
|
|
_logger.LogInformation($"更新订单状态 - OrderNo: {orderNo}, 旧状态: {outboundOrder.OrderStatus}, 新状态: {newStatus}");
|
}
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError($"RecalculateOrderStatus失败 - OrderNo: {orderNo}, Error: {ex.Message}");
|
throw;
|
}
|
}
|
|
|
/// <summary>
|
/// 删除零库存数据(增强版)
|
/// </summary>
|
private async Task DeleteZeroQuantityStockDetails(int stockId)
|
{
|
try
|
{
|
// 查找库存数量为0的记录
|
var zeroStockDetails = await _stockService.StockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
|
.Where(x => x.StockId == stockId && x.StockQuantity <= 0)
|
.ToListAsync();
|
|
if (zeroStockDetails.Any())
|
{
|
await _stockService.StockInfoDetailService.Db.Deleteable(zeroStockDetails).ExecuteCommandAsync();
|
_logger.LogInformation($"删除{zeroStockDetails.Count}条零库存记录 - StockId: {stockId}");
|
}
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError($"DeleteZeroQuantityStockDetails失败 - StockId: {stockId}, Error: {ex.Message}");
|
throw;
|
}
|
}
|
|
private async Task HandleOutboundOrderToMESCompletion(Dt_OutboundOrder outboundOrder, string orderNo)
|
{
|
try
|
{
|
var orderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
|
.LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id)
|
.Where((o, item) => item.OrderNo == orderNo)
|
.Select((o, item) => o)
|
.ToListAsync();
|
|
bool allCompleted = true;
|
foreach (var detail in orderDetails)
|
{
|
_logger.LogInformation($"TaskService HandleOutboundOrderToMESCompletion: {outboundOrder.OrderNo} , {detail.NeedOutQuantity}");
|
if (detail.OverOutQuantity < detail.NeedOutQuantity)
|
{
|
allCompleted = false;
|
break;
|
}
|
}
|
_logger.LogInformation($"TaskService HandleOutboundOrderToMESCompletion: {outboundOrder.OrderNo} , {allCompleted}");
|
int newStatus = allCompleted ? (int)OutOrderStatusEnum.出库完成 : (int)OutOrderStatusEnum.出库中;
|
|
if (outboundOrder.OrderStatus != newStatus)
|
{
|
await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
|
.SetColumns(x => x.OrderStatus == newStatus)
|
.Where(x => x.OrderNo == orderNo)
|
.ExecuteCommandAsync();
|
|
}
|
//只有正常分拣完成时才向MES反馈
|
if (allCompleted && newStatus == (int)OutOrderStatusEnum.出库完成)
|
{
|
|
if (outboundOrder.OrderType == OutOrderTypeEnum.Allocate.ObjToInt())
|
{
|
var allocate = _allocateService.Repository.QueryData(x => x.UpperOrderNo == outboundOrder.UpperOrderNo).First();
|
var allocatefeedmodel = new AllocateDto
|
{
|
ReqCode = Guid.NewGuid().ToString(),
|
ReqTime = DateTime.Now.ToString(),
|
BusinessType = "2",
|
FactoryArea = outboundOrder.FactoryArea,
|
OperationType = 1,
|
Operator = outboundOrder.Operator,
|
OrderNo = outboundOrder.UpperOrderNo,
|
// documentsNO = outboundOrder.OrderNo,
|
// status = outboundOrder.OrderStatus,
|
fromWarehouse = allocate?.FromWarehouse ?? "",
|
toWarehouse = allocate?.ToWarehouse ?? "",
|
Details = new List<AllocateDtoDetail>()
|
|
};
|
foreach (var detail in orderDetails)
|
{
|
// 获取该明细对应的条码信息(从锁定记录)
|
var detailLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.OrderNo == orderNo &&
|
x.OrderDetailId == detail.Id &&
|
(x.Status == (int)OutLockStockStatusEnum.拣选完成 || x.Status == (int)OutLockStockStatusEnum.已回库))
|
.ToListAsync();
|
|
var detailModel = new AllocateDtoDetail
|
{
|
MaterialCode = detail.MaterielCode,
|
LineNo = detail.lineNo,
|
WarehouseCode = detail.WarehouseCode,
|
Qty =0,
|
Unit = detail.BarcodeUnit,
|
Barcodes = new List<BarcodeInfo>()
|
};
|
foreach (var item in detailLocks)
|
{
|
if (item.PickedQty > 0)
|
{
|
var barModel = new BarcodeInfo
|
{
|
Barcode = item.CurrentBarcode,
|
SupplyCode = item.SupplyCode,
|
BatchNo = item.BatchNo,
|
Unit = item.BarcodeUnit,
|
Qty = 0
|
};
|
// 单位不一致时转换
|
if (item.BarcodeUnit != item.Unit)
|
{
|
var convertResult = await _materialUnitService.ConvertAsync(item.MaterielCode, item.PickedQty, item.Unit, item.BarcodeUnit);
|
barModel.Unit = convertResult.Unit;
|
barModel.Qty = convertResult.Quantity;
|
}
|
|
detailModel.Qty += barModel.Qty;
|
detailModel.Barcodes.Add(barModel);
|
}
|
}
|
|
|
allocatefeedmodel.Details.Add(detailModel);
|
}
|
|
var result = await _invokeMESService.FeedbackAllocate(allocatefeedmodel);
|
if (result != null && result.code == 200)
|
{
|
await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
|
.SetColumns(x => x.ReturnToMESStatus == 1)
|
.Where(x => x.OrderId == outboundOrder.Id).ExecuteCommandAsync();
|
|
await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
|
.SetColumns(x => new Dt_OutboundOrder
|
{
|
ReturnToMESStatus = 1,
|
Operator = App.User.UserName,
|
}).Where(x => x.OrderNo == orderNo).ExecuteCommandAsync();
|
}
|
}
|
else if (outboundOrder.OrderType == OutOrderTypeEnum.ReCheck.ObjToInt())
|
{
|
//不用回传
|
}
|
else
|
{
|
var feedmodel = new FeedbackOutboundRequestModel
|
{
|
reqCode = Guid.NewGuid().ToString(),
|
reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
|
business_type = outboundOrder.BusinessType,
|
factoryArea = outboundOrder.FactoryArea,
|
operationType = 1,
|
Operator = outboundOrder.Operator,
|
orderNo = outboundOrder.UpperOrderNo,
|
documentsNO = outboundOrder.OrderNo,
|
status = outboundOrder.OrderStatus,
|
details = new List<FeedbackOutboundDetailsModel>()
|
};
|
|
|
foreach (var detail in orderDetails)
|
{
|
// 获取该明细对应的条码信息(从锁定记录)
|
var detailLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.OrderNo == orderNo &&
|
x.OrderDetailId == detail.Id &&
|
(x.Status == (int)OutLockStockStatusEnum.拣选完成 || x.Status == (int)OutLockStockStatusEnum.已回库))
|
.ToListAsync();
|
|
var detailModel = new FeedbackOutboundDetailsModel
|
{
|
materialCode = detail.MaterielCode,
|
lineNo = detail.lineNo, // 注意:这里可能需要调整字段名
|
warehouseCode = detail.WarehouseCode,
|
qty = 0,
|
currentDeliveryQty =0,
|
unit = detail.Unit,
|
barcodes = new List<WIDESEA_DTO.Outbound.BarcodesModel>()
|
};
|
foreach (var item in detailLocks)
|
{
|
if (item.PickedQty > 0)
|
{
|
var barModel = new WIDESEA_DTO.Outbound.BarcodesModel
|
{
|
barcode = item.CurrentBarcode,
|
supplyCode = item.SupplyCode,
|
batchNo = item.BatchNo,
|
unit = item.BarcodeUnit,
|
qty = item.PickedQty
|
};
|
// 单位不一致时转换
|
if (item.BarcodeUnit != item.Unit)
|
{
|
var convertResult = await _materialUnitService.ConvertAsync(item.MaterielCode, item.PickedQty, item.Unit, item.BarcodeUnit);
|
barModel.unit = convertResult.Unit;
|
barModel.qty = convertResult.Quantity;
|
}
|
|
detailModel.qty += barModel.qty;
|
detailModel.currentDeliveryQty += barModel.qty;
|
detailModel.barcodes.Add(barModel);
|
}
|
}
|
feedmodel.details.Add(detailModel);
|
}
|
var result = await _invokeMESService.FeedbackOutbound(feedmodel);
|
if (result != null && result.code == 200)
|
{
|
await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
|
.SetColumns(x => x.ReturnToMESStatus == 1)
|
.Where(x => x.OrderId == outboundOrder.Id)
|
.ExecuteCommandAsync();
|
|
await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
|
.SetColumns(x => x.ReturnToMESStatus == 1)
|
.Where(x => x.OrderNo == orderNo)
|
.ExecuteCommandAsync();
|
}
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError($"CheckAndUpdateOrderStatus失败 - OrderNo: {orderNo}, Error: {ex.Message}");
|
}
|
|
}
|
|
|
public async Task<WebResponseContent> OutEmptyTaskCompleted(Dt_Task task)
|
{
|
WebResponseContent content = new WebResponseContent();
|
try
|
{
|
Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == task.PalletCode).First();
|
if (stockInfo == null)
|
{
|
return WebResponseContent.Instance.Error($"未找到托盘对应的库存信息");
|
}
|
Dt_LocationInfo locationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == task.SourceAddress);
|
|
if (locationInfo == null)
|
{
|
return content.Error($"未找到对应的终点货位信息");
|
}
|
|
|
int beforeStatus = locationInfo.LocationStatus;
|
|
locationInfo.LocationStatus = LocationStatusEnum.Free.ObjToInt();
|
|
_locationInfoService.Repository.UpdateData(locationInfo);
|
|
|
task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
|
BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
|
_stockService.StockInfoService.Repository.DeleteAndMoveIntoHty(stockInfo, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
|
//_stockRepository.Db.Deleteable(stockInfo).ExecuteCommand();
|
_stockService.StockInfoService.DeleteData(stockInfo);
|
_locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Outbound.ObjToInt(), stockInfo.Details.FirstOrDefault()?.OrderNo ?? "", task.TaskNum);
|
|
return await Task.FromResult(WebResponseContent.Instance.OK());
|
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError($"TaskService OutEmptyTaskCompleted: {ex.Message} ");
|
return await Task.FromResult(WebResponseContent.Instance.Error(ex.Message));
|
}
|
}
|
|
|
|
|
/// <summary>
|
/// 回库完成回调
|
public async Task<WebResponseContent> BackToStockComplete(Dt_Task task)
|
{
|
try
|
{
|
_unitOfWorkManage.BeginTran();
|
|
// 获取相关的出库锁定信息
|
var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
|
.Where(x => x.TaskNum == task.TaskNum &&
|
x.Status == (int)OutLockStockStatusEnum.回库中)
|
.ToListAsync();
|
|
if (!lockInfos.Any())
|
return WebResponseContent.Instance.Error("未找到回库中的锁定信息");
|
|
// 恢复库存出库数量(回库的部分)
|
await RestoreStockOutboundQuantity(lockInfos);
|
|
// 更新出库单明细的锁定数量
|
var orderDetailGroups = lockInfos.GroupBy(x => x.OrderDetailId);
|
|
foreach (var group in orderDetailGroups)
|
{
|
var orderDetailId = group.Key;
|
var totalUnpicked = group.Sum(x => x.AssignQuantity - x.PickedQty);
|
|
if (totalUnpicked > 0)
|
{
|
var orderDetail = await _outboundOrderService.Db.Queryable<Dt_OutboundOrderDetail>()
|
.Where(x => x.Id == orderDetailId)
|
.FirstAsync();
|
orderDetail.LockQuantity -= totalUnpicked;
|
|
// 恢复状态
|
if (orderDetail.LockQuantity <= 0 && orderDetail.OverOutQuantity <= 0)
|
{
|
orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.New;
|
}
|
else if (orderDetail.OverOutQuantity > 0)
|
{
|
orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.AssignOverPartial;
|
}
|
|
await _outboundOrderService.Db.Updateable(orderDetail).ExecuteCommandAsync();
|
}
|
}
|
|
// 更新锁定信息状态为已回库
|
foreach (var lockInfo in lockInfos)
|
{
|
lockInfo.Status = (int)OutLockStockStatusEnum.已回库;
|
}
|
await _outStockLockInfoService.Db.Updateable(lockInfos).ExecuteCommandAsync();
|
|
// 6. 更新库存状态
|
var stockIds = lockInfos.Select(x => x.StockId).Distinct().ToList();
|
var stocks = await _stockService.StockInfoService.Db.Queryable<Dt_StockInfo>()
|
.Where(x => stockIds.Contains(x.Id))
|
.ToListAsync();
|
|
foreach (var stock in stocks)
|
{
|
stock.StockStatus = (int)StockStatusEmun.入库完成;
|
stock.LocationCode = task.TargetAddress; // 更新货位
|
}
|
await _stockService.StockInfoService.Db.Updateable(stocks).ExecuteCommandAsync();
|
|
// 7. 更新货位状态
|
var location = await _locationInfoService.Db.Queryable<Dt_LocationInfo>()
|
.Where(x => x.LocationCode == task.TargetAddress)
|
.FirstAsync();
|
if (location != null)
|
{
|
location.LocationStatus = (int)LocationStatusEnum.InStock;
|
await _locationInfoService.Db.Updateable(location).ExecuteCommandAsync();
|
}
|
|
// 更新任务状态为已完成
|
task.TaskStatus = (int)TaskStatusEnum.Finish;
|
|
await Db.Updateable(task).ExecuteCommandAsync();
|
|
_unitOfWorkManage.CommitTran();
|
|
return WebResponseContent.Instance.OK("回库完成", new
|
{
|
TaskNum = task.TaskNum,
|
PalletCode = task.PalletCode,
|
RestoredQuantity = lockInfos.Sum(x => x.AssignQuantity - x.PickedQty)
|
});
|
}
|
catch (Exception ex)
|
{
|
_unitOfWorkManage.RollbackTran();
|
return WebResponseContent.Instance.Error($"回库完成处理失败: {ex.Message}");
|
}
|
}
|
|
/// <summary>
|
/// 恢复库存出库数量(回库的部分)
|
/// </summary>
|
private async Task RestoreStockOutboundQuantity(List<Dt_OutStockLockInfo> lockInfos)
|
{
|
// 按库存ID和物料分组
|
var stockGroups = lockInfos.GroupBy(x => new { x.StockId, x.MaterielCode });
|
|
foreach (var group in stockGroups)
|
{
|
var stockId = group.Key.StockId;
|
var materielCode = group.Key.MaterielCode;
|
var totalUnpicked = group.Sum(x => x.AssignQuantity - x.PickedQty);
|
|
if (totalUnpicked <= 0) continue;
|
|
// 获取该物料在库存中的所有条码
|
var stockDetails = await _stockService.StockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
|
.Where(x => x.StockId == stockId && x.MaterielCode == materielCode)
|
.ToListAsync();
|
|
if (!stockDetails.Any()) continue;
|
|
// 按出库数量的比例分配恢复数量
|
var totalOutbound = stockDetails.Sum(x => x.OutboundQuantity);
|
|
if (totalOutbound <= 0) continue;
|
|
foreach (var detail in stockDetails)
|
{
|
if (detail.OutboundQuantity <= 0) continue;
|
|
decimal ratio = detail.OutboundQuantity / totalOutbound;
|
decimal restoreAmount = Math.Min(detail.OutboundQuantity, totalUnpicked * ratio);
|
|
detail.OutboundQuantity -= restoreAmount;
|
await _stockService.StockInfoDetailService.Db.Updateable(detail).ExecuteCommandAsync();
|
}
|
}
|
}
|
|
}
|
}
|