using Furion.DatabaseAccessor;
|
using Furion.DependencyInjection;
|
using Furion.DynamicApiController;
|
using Furion.FriendlyException;
|
using Mapster;
|
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.EntityFrameworkCore;
|
using Yitter.IdGenerator;
|
using Admin.NET.Core;
|
|
namespace Admin.NET.Application
|
{
|
/// <summary>
|
/// 出库管理服务
|
/// </summary>
|
[ApiDescriptionSettings("自己的业务", Name = "ExWarehouse", Order = 100)]
|
[Route("api/[Controller]")]
|
public class ExWarehouseService : IDynamicApiController, ITransient
|
{
|
private readonly IRepository<WmsArea, MasterDbContextLocator> _wmsAreaRep;
|
private readonly IRepository<WmsPlace, MasterDbContextLocator> _wmsPlaceRep;
|
private readonly IRepository<WmsTask, MasterDbContextLocator> _wmsTaskRep;
|
private readonly IRepository<WmsContainer, MasterDbContextLocator> _wmsContainerRep;
|
private readonly IRepository<WmsContainerPlace, MasterDbContextLocator> _wmsContainerPlaceRep;
|
private readonly IRepository<WmsMaterial, MasterDbContextLocator> _wmsMaterialRep;
|
private readonly IRepository<WmsMaterialStock, MasterDbContextLocator> _wmsMaterialStockRep;
|
private readonly IRepository<WmsMaterialContainer, MasterDbContextLocator> _wmsMaterialContainerRep;
|
|
/// <summary>
|
/// 构造函数
|
/// </summary>
|
public ExWarehouseService(
|
IRepository<WmsArea, MasterDbContextLocator> wmsAreaRep,
|
IRepository<WmsPlace, MasterDbContextLocator> wmsPlaceRep,
|
IRepository<WmsTask, MasterDbContextLocator> wmsTaskRep,
|
IRepository<WmsContainer, MasterDbContextLocator> wmsContainerRep,
|
IRepository<WmsContainerPlace, MasterDbContextLocator> wmsContainerPlaceRep,
|
IRepository<WmsMaterial, MasterDbContextLocator> wmsMaterialRep,
|
IRepository<WmsMaterialStock, MasterDbContextLocator> wmsMaterialStockRep,
|
IRepository<WmsMaterialContainer, MasterDbContextLocator> wmsMaterialContainerRep
|
)
|
{
|
this._wmsAreaRep = wmsAreaRep;
|
this._wmsPlaceRep = wmsPlaceRep;
|
this._wmsTaskRep = wmsTaskRep;
|
this._wmsContainerRep = wmsContainerRep;
|
this._wmsContainerPlaceRep = wmsContainerPlaceRep;
|
this._wmsMaterialRep = wmsMaterialRep;
|
this._wmsMaterialStockRep = wmsMaterialStockRep;
|
this._wmsMaterialContainerRep = wmsMaterialContainerRep;
|
}
|
|
|
|
|
/// <summary>
|
/// 分页查询物料出库管理信息
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[HttpGet("page")]
|
public async Task<PageResult<ExWareHouseOutput>> Page([FromQuery] ExWarehouseSearch input)
|
{
|
var wmsMaterialStocks = await _wmsMaterialStockRep.DetachedEntities
|
.Where (!string.IsNullOrEmpty(input.MaterialName), u => EF.Functions.Like(u.MaterialName, $"%{input.MaterialName.Trim()}%"))
|
.ProjectToType<ExWareHouseOutput>()
|
.ToListAsync();
|
return wmsMaterialStocks.ToADPagedList(input.PageNo, input.PageSize);
|
}
|
|
/// <summary>
|
/// 自动出库
|
/// </summary>
|
/// <param name="inputs"></param>
|
/// <returns></returns>
|
[HttpPost("AutoExWarehouse")]
|
[UnitOfWork]
|
public async Task AutoExWarehouse(List<ExWarehouseInput> inputs)
|
{
|
// 根据托盘号、库位编号去重
|
var containerCodeDistinct = inputs.Select(u => new { u.ContainerCode, u.PlaceCode }).Distinct().ToList();
|
if (containerCodeDistinct.Count <= 0) throw Oops.Oh("暂无库存出库");
|
|
// 查询库区名称
|
var wmsArea = await _wmsAreaRep.FirstOrDefaultAsync(u => u.AreaName.Contains("绝缘立库"));
|
if (wmsArea != null) throw Oops.Oh("库区不存在");
|
|
foreach (var item in containerCodeDistinct)
|
{
|
var wmsMaterialContainerList = new List<WmsMaterialContainer>();
|
// 判断任务
|
var wmsTask = await _wmsTaskRep.FirstOrDefaultAsync(p => p.ContainerCode == item.ContainerCode && p.TaskStatus != TaskStatusEnum.WANCHENG);
|
if (wmsTask != null) throw Oops.Oh("周转箱号存在未完成的任务!");
|
|
// 检查周转箱号信息
|
var wmsContainer = await _wmsContainerRep.FirstOrDefaultAsync(n => n.ContainerCode == item.ContainerCode);
|
if (wmsContainer == null) throw Oops.Oh("库存中没有该:" + wmsContainer.ContainerCode + "托盘!");
|
|
// 检查库位信息
|
var wmsPlace = await _wmsPlaceRep.FirstOrDefaultAsync(p => p.PlaceCode == item.PlaceCode);
|
if (wmsPlace == null) throw Oops.Oh("库位不存在!");
|
if (wmsPlace.Islock == YesOrNot.Y) throw Oops.Oh("库位被锁定!");
|
|
// 更新状态为“待出”
|
wmsPlace.PlaceStatus = PlaceStatus.DAICHU;
|
await _wmsPlaceRep.UpdateAsync(wmsPlace);
|
|
// 检查库存
|
var wmsMaterialStockList = inputs.Where(u => u.ContainerCode == wmsContainer.ContainerCode && u.PlaceCode == wmsPlace.PlaceCode).ToList();
|
if (wmsMaterialStockList.Count <= 0) throw Oops.Oh("库存数据异常!");
|
|
// 检查库位与周转箱号关系
|
var wmsContainerPlace = await _wmsContainerPlaceRep.FirstOrDefaultAsync(p => p.ContainerCode == wmsContainer.ContainerCode && p.ContainerId == wmsContainer.Id
|
&& p.PlaceCode == wmsPlace.PlaceCode && p.PlaceId == wmsPlace.Id && p.ContainerPlaceStatus == CommonStatus.ENABLE);
|
if (wmsContainerPlace == null) throw Oops.Oh("托盘号与库位关系不存在!");
|
|
// 不是空料箱才会有组盘关系
|
if (wmsPlace.EmptyContainer == YesOrNot.N)
|
{
|
// 检查物料与周转箱号关系
|
wmsMaterialContainerList = await _wmsMaterialContainerRep.Where(p => p.ContainerCode == wmsContainer.ContainerCode && p.BindStatus == CommonStatus.ENABLE).ToListAsync();
|
if (wmsMaterialContainerList.Count <= 0) throw Oops.Oh("周转箱号与物料关系不存在!");
|
}
|
else
|
{
|
// 更新空料箱库存
|
var wmsMaterialStock = await _wmsMaterialStockRep.FirstOrDefaultAsync(u => u.ContainerCode == wmsContainer.ContainerCode);
|
if (wmsMaterialStock.Source == RuKuSourceEnum.KONGTUO)
|
{
|
wmsMaterialStock.PlaceCode = "N/A";
|
await _wmsMaterialStockRep.UpdateAsync(wmsMaterialStock);
|
}
|
}
|
if (wmsTask == null)
|
{
|
string taskNo = "CHUKU" + DateTime.Today.ToString("yyyyMMdd");
|
var wmsTaskModel = await _wmsTaskRep.DetachedEntities.FirstOrDefaultAsync(u => EF.Functions.Like(u.TaskNo, $"%{taskNo}%"));
|
if (wmsTaskModel == null)
|
{
|
taskNo = taskNo + "0001";
|
}
|
else
|
{
|
//获取流水号最大的数据
|
var maxSerialNumber = await _wmsTaskRep.MaxAsync(t => t.TaskNo);
|
taskNo = Comm.GenerateNewInvoiceNumber(maxSerialNumber, 1);
|
}
|
|
// 新增任务
|
var takmodel = new WmsTask()
|
{
|
TaskNo = taskNo,//YitIdHelper.NextId().ToString(),
|
TaskModel = TaskModel.QUANZIDONG,
|
TaskType = TaskType.CHUKU,
|
TaskLevel = 1,
|
TaskStatus = TaskStatusEnum.WEIZHIXING,
|
ContainerCode = wmsContainer.ContainerCode,
|
SourcePlace = wmsPlace.PlaceCode,
|
Aisle = wmsPlace.Aisle,
|
ToPlace = "出库口",
|
AreaName = wmsArea.AreaName,
|
Description = wmsPlace.EmptyContainer == YesOrNot.Y ? "空托" : "物料",
|
OrderNo = wmsMaterialContainerList.Count <= 0 ? "N/A" : wmsMaterialContainerList.FirstOrDefault().OrderNo,
|
TaskDodeviceStatus = TaskDodeviceStatusEnum.W,
|
IsRead = true
|
};
|
await _wmsTaskRep.InsertAsync(takmodel);
|
}
|
}
|
}
|
|
/// <summary>
|
/// 人工出库
|
/// </summary>
|
/// <param name="inputs"></param>
|
/// <returns></returns>
|
[HttpPost("manualExWarehouse")]
|
[UnitOfWork]
|
public async Task ManualExWarehouse(List<ExWarehouseInput> inputs)
|
{
|
// 根据托盘号、库位编号去重
|
var containerCodeDistinct = inputs.Select(u => new { u.ContainerCode, u.PlaceCode }).Distinct().ToList();
|
if (containerCodeDistinct.Count <= 0) throw Oops.Oh("暂无库存出库");
|
|
// 查询库区名称
|
var wmsArea = await _wmsAreaRep.FirstOrDefaultAsync(u => u.AreaName.Contains("绝缘立库"));
|
if (wmsArea != null) throw Oops.Oh("库区不存在");
|
|
foreach (var item in containerCodeDistinct)
|
{
|
var wmsMaterialContainerList = new List<WmsMaterialContainer>();
|
// 判断任务
|
var wmsTask = await _wmsTaskRep.FirstOrDefaultAsync(p => p.ContainerCode == item.ContainerCode && p.TaskStatus != TaskStatusEnum.WANCHENG);
|
if (wmsTask != null) throw Oops.Oh("托盘号存在未完成的任务!");
|
|
// 检查托盘号信息
|
var wmsContainer = await _wmsContainerRep.FirstOrDefaultAsync(n => n.ContainerCode == item.ContainerCode);
|
if (wmsContainer == null) throw Oops.Oh("周转箱号不存在!");
|
|
// 检查库位信息
|
var wmsPlace = await _wmsPlaceRep.FirstOrDefaultAsync(p => p.PlaceCode == item.PlaceCode);
|
if (wmsPlace == null) throw Oops.Oh("库位不存在!");
|
if (wmsPlace.Islock == YesOrNot.Y) throw Oops.Oh("库位被锁定!");
|
|
// 检查库存
|
var wmsMaterialStockList = inputs.Where(u => u.ContainerCode == wmsContainer.ContainerCode && u.PlaceCode == wmsPlace.PlaceCode).ToList();
|
if (wmsMaterialStockList.Count <= 0) throw Oops.Oh("库存数据异常!");
|
|
// 检查库位与托盘号关系
|
var wmsContainerPlace = await _wmsContainerPlaceRep.FirstOrDefaultAsync(p => p.ContainerCode == wmsContainer.ContainerCode && p.ContainerId == wmsContainer.Id
|
&& p.PlaceCode == wmsPlace.PlaceCode && p.PlaceId == wmsPlace.Id && p.ContainerPlaceStatus == CommonStatus.ENABLE);
|
if (wmsContainerPlace == null) throw Oops.Oh("托盘号与库位关系不存在!");
|
|
|
// 不是空托才会有组盘关系
|
if (wmsPlace.EmptyContainer == YesOrNot.N)
|
{
|
// 检查物料与空托号关系
|
wmsMaterialContainerList = await _wmsMaterialContainerRep.Where(p => p.ContainerCode == wmsContainer.ContainerCode && p.BindStatus == CommonStatus.ENABLE).ToListAsync();
|
if (wmsMaterialContainerList.Count <= 0) throw Oops.Oh("托盘号与物料关系不存在!");
|
}
|
else
|
{
|
// 更新空料箱库存
|
var wmsMaterialStock = await _wmsMaterialStockRep.FirstOrDefaultAsync(u => u.ContainerCode == wmsContainer.ContainerCode);
|
if (wmsMaterialStock.Source == RuKuSourceEnum.KONGTUO)
|
{
|
await _wmsMaterialStockRep.DeleteAsync(wmsMaterialStock);
|
}
|
}
|
|
if (wmsTask == null)
|
{
|
//构建出库物料和周转箱号关系
|
var orderNo = "N/A";
|
if (wmsMaterialContainerList.Count > 0) orderNo = YitIdHelper.NextId().ToString();
|
|
foreach (var wmsMaterialContaine in wmsMaterialContainerList)
|
{
|
//更新状态为”删除“
|
wmsMaterialContaine.BindStatus = CommonStatus.DELETED;
|
await _wmsMaterialContainerRep.UpdateNowAsync(wmsMaterialContaine);
|
|
//新增组盘绑定记录 正常
|
var addWmsMaterialContainer = wmsMaterialContaine;
|
addWmsMaterialContainer.Id = YitIdHelper.NextId();
|
addWmsMaterialContainer.OrderNo = orderNo;
|
addWmsMaterialContainer.BindStatus = CommonStatus.ENABLE;
|
await _wmsMaterialContainerRep.InsertNowAsync(addWmsMaterialContainer);
|
// 这里没有分拣操作直接更新库存信息
|
var wmsMaterialStock = await _wmsMaterialStockRep.FirstOrDefaultAsync(u => u.ContainerCode == wmsMaterialContaine.ContainerCode);
|
wmsMaterialStock.PlaceCode = "N/A";
|
wmsMaterialStock.StockNumber -= wmsMaterialContaine.BindQuantity;
|
await _wmsMaterialStockRep.UpdateAsync(wmsMaterialStock);
|
}
|
|
string taskNo = "CHUKU" + DateTime.Today.ToString("yyyyMMdd");
|
var wmsTaskModel = await _wmsTaskRep.DetachedEntities.FirstOrDefaultAsync(u => EF.Functions.Like(u.TaskNo, $"%{taskNo}%"));
|
if (wmsTaskModel == null)
|
{
|
taskNo = taskNo + "0001";
|
}
|
else
|
{
|
//获取流水号最大的数据
|
var maxSerialNumber = await _wmsTaskRep.MaxAsync(t => t.TaskNo);
|
taskNo = Comm.GenerateNewInvoiceNumber(maxSerialNumber, 1);
|
}
|
// 新增任务
|
var addWmsTask = new WmsTask()
|
{
|
TaskNo = taskNo,//YitIdHelper.NextId().ToString(),
|
TaskModel = TaskModel.SHOUDONG,
|
TaskType = TaskType.CHUKU,
|
TaskLevel = 1,
|
TaskStatus = TaskStatusEnum.WANCHENG,
|
ContainerCode = wmsContainer.ContainerCode,
|
SourcePlace = wmsPlace.PlaceCode,
|
Aisle = wmsPlace.Aisle,
|
ToPlace = "出库口",
|
AreaName = wmsArea.AreaName,
|
Description = wmsPlace.EmptyContainer == YesOrNot.Y ? "空托" : "物料",
|
OrderNo = orderNo,
|
TaskDodeviceStatus=TaskDodeviceStatusEnum.W,
|
UpdatedTime = DateTime.Now,
|
};
|
await _wmsTaskRep.InsertAsync(addWmsTask);
|
|
// 更新库位与周转箱号关系表状态为“删除”
|
wmsContainerPlace.ContainerPlaceStatus = CommonStatus.DELETED;
|
await _wmsContainerPlaceRep.UpdateAsync(wmsContainerPlace);
|
|
// 更新库位为“空闲”
|
wmsPlace.PlaceStatus = PlaceStatus.KONGXIAN;
|
wmsPlace.Islock = YesOrNot.N;
|
wmsPlace.EmptyContainer = YesOrNot.N;
|
await _wmsPlaceRep.UpdateAsync(wmsPlace);
|
|
// 更新周转箱号状态为“空闲”
|
wmsContainer.ContainerStatus = ContainerStatus.KOUXIAN;
|
await _wmsContainerRep.UpdateAsync(wmsContainer);
|
}
|
}
|
}
|
|
|
/// <summary>
|
/// 呼叫空托
|
/// </summary>
|
/// <returns></returns>
|
[HttpPost("callairflare")]
|
[UnitOfWork]
|
public async Task CallAirflare(CallAirflareInput input)
|
{
|
//获取库位中存货是空托的库位
|
var wmsPlace = await _wmsPlaceRep.Where(u => u.PlaceStatus == PlaceStatus.CUNHUO && u.EmptyContainer== YesOrNot.Y).ToListAsync();
|
if (wmsPlace.Count > 0)
|
{
|
|
}
|
}
|
}
|
}
|