using MailKit.Search;
|
using Masuit.Tools;
|
using System.Linq.Expressions;
|
using WIDESEA_Common;
|
using WIDESEA_Core;
|
using WIDESEA_Core.BaseRepository;
|
using WIDESEA_Core.BaseServices;
|
using WIDESEA_Core.Enums;
|
using WIDESEA_Core.Helper;
|
using WIDESEA_DTO;
|
using WIDESEA_DTO.Order;
|
using WIDESEA_DTO.Stock;
|
using WIDESEA_DTO.WMS;
|
using WIDESEA_IBusinessesRepository;
|
using WIDESEA_IOrderRepository;
|
using WIDESEA_IOrderServices;
|
using WIDESEA_IStorageBasicRepository;
|
using WIDESEA_IStorageBasicService;
|
using WIDESEA_IStorageTaskRepository;
|
using WIDESEA_IStorageTaskServices;
|
using WIDESEA_Model.Models;
|
using WIDESEA_Model.Models.ERP;
|
using WIDESEA_Model.Models.Order;
|
using WIDESEA_OrderRepository;
|
using WIDESEA_StorageTaskRepository;
|
using WIDESEA_StorageTaskServices;
|
|
namespace WIDESEA_OrderServices
|
{
|
public class Dt_AllocateOutboundOrderService : ServiceBase<Dt_AllocateOutboundOrder, IDt_AllocateOutboundOrderRepository>, IDt_AllocateOutboundOrderService
|
{
|
private readonly IUnitOfWorkManage _unitOfWorkManage;
|
private readonly IDt_AllocateOutboundOrderDetailRepository _allocateoutboundOrderDetailRepository;
|
private readonly IStockInfoDetailRepository _stockInfoDetailRepository;
|
private readonly IStockInfoRepository _stockInfoRepository;
|
private readonly IStockInfoService _stockInfoService;
|
private readonly IDt_TaskService _taskService;
|
private readonly ILocationInfoRepository _locationRepository;
|
private readonly IDt_TaskRepository _taskRepository;
|
private readonly ILocationStatusChangeRecordRepository _locationStatusChangeRecordRepository;
|
private readonly IDt_OrderOutDetailsRepository _outDetailsRepository;
|
private readonly IDt_AreaInfoRepository _areaInfoRepository;
|
|
public Dt_AllocateOutboundOrderService(IDt_AllocateOutboundOrderRepository BaseDal,
|
IUnitOfWorkManage unitOfWorkManage,
|
IDt_AllocateOutboundOrderDetailRepository allocateoutboundOrderDetailRepository,
|
IStockInfoDetailRepository stockInfoDetailRepository,
|
IStockInfoRepository stockInfoRepository,
|
IStockInfoService stockInfoService,
|
IDt_TaskService taskService,
|
ILocationInfoRepository locationRepository,
|
IDt_TaskRepository taskRepository,
|
ILocationStatusChangeRecordRepository locationStatusChangeRecordRepository,
|
IDt_OrderOutDetailsRepository outDetailsRepository,
|
IDt_AreaInfoRepository areaInfoRepository) : base(BaseDal)
|
{
|
_unitOfWorkManage = unitOfWorkManage;
|
_allocateoutboundOrderDetailRepository = allocateoutboundOrderDetailRepository;
|
_stockInfoDetailRepository = stockInfoDetailRepository;
|
_stockInfoRepository = stockInfoRepository;
|
_stockInfoService = stockInfoService;
|
_taskService = taskService;
|
_locationRepository = locationRepository;
|
_taskRepository = taskRepository;
|
_locationStatusChangeRecordRepository = locationStatusChangeRecordRepository;
|
_outDetailsRepository = outDetailsRepository;
|
_areaInfoRepository = areaInfoRepository;
|
}
|
public WebResponseContent GetAllocateOutboundOrder(OutboundOrderGetDTO outboundOrderGetDTO)
|
{
|
WebResponseContent content = new WebResponseContent();
|
try
|
{
|
Expression<Func<Dt_AllocateOutboundOrder, bool>> expressionOrder = x => true;
|
if (!string.IsNullOrEmpty(outboundOrderGetDTO.OrderNo))
|
{
|
expressionOrder = x => x.UpperOrderNo.Contains(outboundOrderGetDTO.OrderNo);
|
}
|
int count = 0;
|
if (outboundOrderGetDTO.OrderNo == "")
|
{
|
count = BaseDal.QueryData(x => x.OrderStatus != (int)OrderStateEmun.已完成).ToList().Count();
|
}
|
else
|
{
|
count = BaseDal.QueryData(x => x.OrderStatus != (int)OrderStateEmun.已完成 && x.UpperOrderNo == outboundOrderGetDTO.OrderNo).ToList().Count();
|
}
|
|
int maxPage = Convert.ToInt32(Math.Ceiling(count / 10.0));
|
if (outboundOrderGetDTO.pageNo <= maxPage)
|
{
|
var outboundOrder = BaseDal.Db.Queryable<Dt_AllocateOutboundOrder>().Where(expressionOrder).OrderByDescending(x => x.CreateDate).Skip((outboundOrderGetDTO.pageNo - 1) * 10).Take(10).Select(x => new Dt_AllocateOutboundOrder
|
{
|
OrderNo = x.OrderNo,
|
Id = x.Id,
|
UpperOrderNo = x.UpperOrderNo,
|
CreateDate = x.CreateDate,
|
Creater = x.Creater
|
}).ToList();
|
|
content = WebResponseContent.Instance.OK(data: outboundOrder);
|
}
|
else
|
{
|
var outboundOrder = BaseDal.Db.Queryable<Dt_AllocateOutboundOrder>().Where(expressionOrder).OrderByDescending(x => x.CreateDate).Skip(0 * 10).Take(10).Select(x => new Dt_AllocateOutboundOrder
|
{
|
OrderNo = x.OrderNo,
|
Id = x.Id,
|
UpperOrderNo = x.UpperOrderNo,
|
CreateDate = x.CreateDate,
|
Creater = x.Creater
|
}).ToList();
|
|
content = WebResponseContent.Instance.OK(data: outboundOrder);
|
}
|
}
|
catch (Exception ex)
|
{
|
content = WebResponseContent.Instance.Error($"查询出库单据错误,错误信息:{ex.Message}");
|
}
|
return content;
|
}
|
|
public WebResponseContent GetAllocateOutboundOrderDetail(OutboundOrderGetDTO outboundOrderGetDTO)
|
{
|
WebResponseContent content = new WebResponseContent();
|
try
|
{
|
var otheroutboundOrder = BaseDal.QueryFirst(x => x.Id == outboundOrderGetDTO.id);
|
|
Expression<Func<Dt_AllocateOutboundOrderDetail, bool>> expression = x => x.OrderId == otheroutboundOrder.Id;
|
if (!string.IsNullOrEmpty(outboundOrderGetDTO.searchValue))
|
{
|
expression = x => x.OrderId == otheroutboundOrder.Id && x.MaterielCode.Contains(outboundOrderGetDTO.searchValue);
|
}
|
|
var outboundOrderdetail = _allocateoutboundOrderDetailRepository.Db.Queryable<Dt_AllocateOutboundOrderDetail>().Where(expression).Where(x => x.OrderQuantity > x.OverOutQuantity).Select(x => new Dt_AllocateOutboundOrderDetail { MaterielCode = x.MaterielCode, MaterielName = x.MaterielName, OrderQuantity = x.OrderQuantity, OverOutQuantity = x.OverOutQuantity, Id = x.Id }).ToList();
|
content = WebResponseContent.Instance.OK(data: outboundOrderdetail);
|
}
|
catch (Exception ex)
|
{
|
content = WebResponseContent.Instance.Error($"查询出库单据错误,错误信息:{ex.Message}");
|
}
|
return content;
|
}
|
|
#region 根据单据明细生成出库任务
|
|
public async Task<WebResponseContent> GenerateAllocateOutboundTask(GenerateOutTaskDto requestOut)
|
{
|
WebResponseContent content = new WebResponseContent();
|
try
|
{
|
foreach (var orderId in requestOut.orderIds)
|
{
|
Dt_AreaInfo areaInfo = null;
|
if (requestOut.Warehouse != "")
|
areaInfo = _areaInfoRepository.QueryFirst(x => x.AreaCode == requestOut.Warehouse);
|
|
|
List<RequestTaskDto> taskDtos = new List<RequestTaskDto>();
|
Dt_AllocateOutboundOrderDetail allocateoutboundOrderdetail = _allocateoutboundOrderDetailRepository.QueryFirst(x => x.Id == orderId);
|
Dt_AllocateOutboundOrder outboundOrder = BaseDal.QueryFirst(x => x.Id == allocateoutboundOrderdetail.OrderId);
|
|
(bool, string) checkResult = CheckSelectStockDeital(allocateoutboundOrderdetail, requestOut.stockViews, requestOut);
|
if (!checkResult.Item1) throw new Exception(checkResult.Item2);
|
|
else
|
{
|
var result = AssignStockOutbound(allocateoutboundOrderdetail, requestOut.stockViews);
|
|
if (result.Item1.Count <= 0)
|
{
|
return content.Error($"订单{outboundOrder.UpperOrderNo}物料编码{allocateoutboundOrderdetail.MaterielCode}未找到库存分配,请确认是否存在库存或单据数量已出完");
|
}
|
List<Dt_OrderOutDetails> outDetails = new List<Dt_OrderOutDetails>();
|
result.Item1.Distinct().ForEach(item =>
|
{
|
RequestTaskDto task = new RequestTaskDto
|
{
|
TaskType = outboundOrder.OrderType,
|
OrderNo = outboundOrder.OrderNo,
|
MaterielCode = allocateoutboundOrderdetail.MaterielCode,
|
Position = item.LocationCode,
|
PalletCode = item.PalletCode,
|
AreaId = Convert.ToInt32(requestOut.AreaId),
|
};
|
taskDtos.Add(task);
|
item.StockInfoDetails.Where(x => x.MaterielCode == allocateoutboundOrderdetail.MaterielCode).FirstOrDefault().Status = (int)StockStateEmun.出库锁定;
|
item.StockStatus = (int)StockStateEmun.出库锁定;
|
item.OrderNo = outboundOrder.UpperOrderNo;
|
|
item.StockInfoDetails.Where(x => x.OutboundQuantity > 0 && x.MaterielCode == allocateoutboundOrderdetail.MaterielCode).ForEach(x =>
|
{
|
outDetails.Add(new Dt_OrderOutDetails()
|
{
|
OrderNo = outboundOrder.UpperOrderNo,
|
PalletCode = item.PalletCode,
|
OrderType = outboundOrder.OrderType,
|
ERPOrderId = allocateoutboundOrderdetail.ERPOrderId,
|
MaterielCode = allocateoutboundOrderdetail.MaterielCode,
|
MaterielName = allocateoutboundOrderdetail.MaterielName,
|
AllocateWarehouse = areaInfo == null ? item.StockInfoDetails.Where(x => x.MaterielCode == allocateoutboundOrderdetail.MaterielCode).FirstOrDefault().Warehouse : areaInfo.AreaName,
|
AllocateWarehouseId = areaInfo == null ? item.StockInfoDetails.Where(x => x.MaterielCode == allocateoutboundOrderdetail.MaterielCode).FirstOrDefault().WareHouseId : areaInfo.AreaCode,
|
Warehouse = "智能立库",
|
WareHouseId = "107",
|
OutboundQuantity = x.OutboundQuantity,
|
});
|
});
|
});
|
List<Dt_Task> taskNews = new List<Dt_Task>();
|
List<WMSTaskDTO> taskDTOs = new List<WMSTaskDTO>();
|
foreach (var item in taskDtos)
|
{
|
taskNews.Add(await _taskService.RequestOutboundTaskAsync(item));
|
}
|
List<DtLocationStatusChangeRecord> locationStatusChangeRecords = new List<DtLocationStatusChangeRecord>();
|
List<DtLocationInfo> locations = new List<DtLocationInfo>();
|
if(taskNews.Count <= 0)
|
{
|
throw new Exception($"{allocateoutboundOrderdetail.MaterielCode}未找到可出库托盘");
|
}
|
foreach (var item in taskNews)
|
{
|
taskDTOs.Add(CreateTaskDTO(item));
|
var result1 = _taskService.UpdateLocationStatus(item.SourceAddress, LocationEnum.InStockDisable, item.TaskNum.Value, (int)StatusChangeTypeEnum.AutomaticOutbound);
|
var result2 = _taskService.UpdateLocationStatus(item.TargetAddress, LocationEnum.Lock, item.TaskNum.Value, (int)StatusChangeTypeEnum.AutomaticOutbound);
|
locationStatusChangeRecords.AddRange(result1.Item1);
|
locationStatusChangeRecords.AddRange(result2.Item1);
|
locations.AddRange(result1.Item2);
|
locations.AddRange(result2.Item2);
|
}
|
|
await _unitOfWorkManage.UseTranAsync(async () =>
|
{
|
_taskRepository.AddData(taskNews);
|
_stockInfoRepository.UpdateDataNav(result.Item1);
|
await _locationStatusChangeRecordRepository.AddDataAsync(locationStatusChangeRecords);
|
await _locationRepository.UpdateDataAsync(locations);
|
_allocateoutboundOrderDetailRepository.UpdateData(result.Item2);
|
_outDetailsRepository.AddData(outDetails);
|
});
|
content = await _taskService.SendWCSTask(taskDTOs);
|
}
|
}
|
return content;
|
}
|
catch (Exception ex)
|
{
|
return content.Error(ex.Message);
|
}
|
|
}
|
private WMSTaskDTO CreateTaskDTO(Dt_Task task)
|
{
|
return new WMSTaskDTO
|
{
|
TaskNum = task.TaskNum.Value,
|
Grade = task.Grade.Value,
|
PalletCode = task.PalletCode,
|
RoadWay = task.Roadway,
|
SourceAddress = task.SourceAddress,
|
TargetAddress = task.TargetAddress,
|
TaskState = task.TaskState,
|
Id = 0,
|
TaskType = task.TaskType,
|
AGVTaskNum = task.AGVTaskNum,
|
Remark = task.Remark
|
};
|
}
|
public (List<DtStockInfo>, Dt_AllocateOutboundOrderDetail) AssignStockOutbound(Dt_AllocateOutboundOrderDetail allocateoutboundOrderdetail, List<StockSelectViewDTO> stockSelectViews)
|
{
|
decimal originalNeedQuantity = allocateoutboundOrderdetail.OrderQuantity - allocateoutboundOrderdetail.OverOutQuantity;
|
|
decimal needQuantity = originalNeedQuantity;
|
|
List<DtStockInfo> outStocks = new List<DtStockInfo>();
|
if (stockSelectViews != null && stockSelectViews.Count > 0)
|
{
|
outStocks = BaseDal.Db.Queryable<DtStockInfo>().Where(x => stockSelectViews.Select(x => x.PalletCode).ToList().Contains(x.PalletCode)).Includes(x => x.StockInfoDetails).ToList();
|
}
|
else
|
{
|
outStocks = GetStockInfos(allocateoutboundOrderdetail.MaterielCode);
|
}
|
|
List<DtStockInfo> outStockNews = new List<DtStockInfo>();
|
|
foreach (var item in outStocks)
|
{
|
var stockDetail = item.StockInfoDetails
|
.Where(d => d.MaterielCode == allocateoutboundOrderdetail.MaterielCode && d.Quantity > 0);
|
if (needQuantity <= 0)
|
{
|
continue;
|
}
|
foreach (var detail in stockDetail)
|
{
|
if (detail != null)
|
{
|
if (needQuantity >= detail.Quantity)
|
{
|
if (detail.Quantity <= detail.OutboundQuantity)
|
{
|
continue;
|
}
|
needQuantity -= detail.Quantity;
|
detail.OutboundQuantity = detail.Quantity;
|
}
|
else
|
{
|
if (detail.Quantity <= detail.OutboundQuantity)
|
{
|
continue;
|
}
|
detail.OutboundQuantity = needQuantity;
|
needQuantity = 0;
|
}
|
outStockNews.Add(item);
|
}
|
}
|
|
}
|
allocateoutboundOrderdetail.OverOutQuantity = allocateoutboundOrderdetail.OrderQuantity - needQuantity;
|
|
if (allocateoutboundOrderdetail.OverOutQuantity != 0)
|
{
|
allocateoutboundOrderdetail.OrderDetailStatus = (int)OrderStateEmun.开始;
|
}
|
return (outStockNews, allocateoutboundOrderdetail);
|
}
|
|
private (bool, string) CheckSelectStockDeital(Dt_AllocateOutboundOrderDetail allocateoutboundOrderdetail, List<StockSelectViewDTO> stockSelectViews, GenerateOutTaskDto requestOut)
|
{
|
if (allocateoutboundOrderdetail == null)
|
{
|
return (false, "未找到出库单信息");
|
}
|
if (allocateoutboundOrderdetail.OrderDetailStatus == (int)OrderStateEmun.已完成)
|
{
|
return (false, "该明细不可操作");
|
}
|
if (stockSelectViews != null && stockSelectViews.Sum(x => x.UseableQuantity) > allocateoutboundOrderdetail.OrderQuantity - allocateoutboundOrderdetail.OverOutQuantity)
|
{
|
return (false, "选择数量超出单据数量");
|
}
|
if (allocateoutboundOrderdetail.OrderQuantity <= allocateoutboundOrderdetail.OverOutQuantity)
|
{
|
return (false, "单据数量已出库完成");
|
}
|
return (true, "成功");
|
}
|
|
public List<DtStockInfo> GetStockInfos(string materielCode)
|
{
|
var stocks = BaseDal.Db.Queryable<DtStockInfo>()
|
.Includes(x => x.StockInfoDetails)
|
.Includes(x => x.LocationInfo)
|
.Where(x => x.LocationInfo.LocationStatus == (int)LocationEnum.InStock && x.LocationInfo.EnalbeStatus == (int)EnableEnum.Enable)
|
.Where(x => x.StockInfoDetails.Any(d => d.MaterielCode == materielCode && d.Quantity > 0)).ToList().OrderBy(x => x.CreateDate).ToList();
|
|
if (stocks == null || stocks.Count() <= 0)
|
{
|
return stocks;
|
}
|
|
var locations = stocks.Select(s => s.LocationInfo).ToList();
|
List<DtLocationInfo> locationInfos = _stockInfoService.GetStockLocations(locations).Distinct().ToList();
|
stocks = stocks.Where(s => s.LocationInfo != null && locationInfos.Contains(s.LocationInfo)).ToList();
|
return stocks;
|
}
|
#endregion 根据单据明细生成出库任务
|
}
|
}
|