using Admin.NET.Application.Common.FindEmptyLocationFactory;
using Admin.NET.Application.Common;
using Furion;
using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using iWare.Wms.Core;
using iWare.Wms.Core.Enum;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq.Dynamic.Core;
namespace iWare.Wms.Application
{
///
/// 出库管理
///
[ApiDescriptionSettings("仓库作业", Name = "IExWarehouse", Order = 100)]
[Route("api/[Controller]")]
[DisableOpLog]
public class ExWarehouseService : IExWarehouseService, IDynamicApiController, ITransient
{
private readonly IRepository _wmsContainerRep;
private readonly IRepository _wmsMaterialRep;
private readonly IRepository _wmsMaterialContainerRep;
private readonly IRepository _wmsAreaRep;
private readonly IRepository _wmsPlaceRep;
private readonly IRepository _wmsTaskRep;
private readonly IRepository _wmsMaterialStockRep;
private readonly IRepository _wmsContainerPlaceRep;
private readonly IRepository _sysUser;
private readonly IRepository _wareSite;
private readonly IRepository _wmsPart;
private readonly IRepository _v_ware_inventory_by_container;
private readonly IRepository _wareTask;
private readonly IRepository _wmsContainerType;
private readonly IRepository _v_empty_location;
private readonly IRepository _wareLocationVsContainer;
private readonly IRepository _v_EmptyLocationRep;
public ExWarehouseService(
IRepository wmsContainerRep,
IRepository wmsMaterialRep,
IRepository wmsMaterialContainerRep,
IRepository wmsAreaRep,
IRepository wmsPlaceRep,
IRepository wmsTaskRep,
IRepository wmsMaterialStockRep,
IRepository wmsContainerPlaceRep,
IRepository sysUser,
IRepository wareSite,
IRepository wmsPart,
IRepository v_ware_inventory_by_container,
IRepository wareTask,
IRepository wmsContainerType,
IRepository v_empty_location,
IRepository wareLocationVsContainer,
IRepository v_EmptyLocationRep
)
{
_wmsContainerRep = wmsContainerRep;
_wmsMaterialRep = wmsMaterialRep;
_wmsMaterialContainerRep = wmsMaterialContainerRep;
_wmsAreaRep = wmsAreaRep;
_wmsPlaceRep = wmsPlaceRep;
_wmsTaskRep = wmsTaskRep;
_wmsMaterialStockRep = wmsMaterialStockRep;
_wmsContainerPlaceRep = wmsContainerPlaceRep;
_sysUser = sysUser;
_wareSite = wareSite;
_wmsPart = wmsPart;
_v_ware_inventory_by_container = v_ware_inventory_by_container;
_wareTask = wareTask;
_wmsContainerType = wmsContainerType;
_v_empty_location = v_empty_location;
_wareLocationVsContainer = wareLocationVsContainer;
_v_EmptyLocationRep = v_EmptyLocationRep;
}
///
/// 分页查询库存表
///
///
///
[HttpGet("page")]
public async Task> Page([FromQuery] WmsMaterialStockSearch input)
{
//var wmsMaterialStocks = await _wmsMaterialStockRep.DetachedEntities
// .Where(!string.IsNullOrEmpty(input.Materialno), u => EF.Functions.Like(u.MaterialNo, $"%{input.Materialno.Trim()}%"))
// .Where(input.Materialtype != null, u => u.MaterialType == input.Materialtype)
// .Where(!string.IsNullOrEmpty(input.Materialbatch), u => EF.Functions.Like(u.MaterialBatch, $"%{input.Materialbatch.Trim()}%"))
// .Where(!string.IsNullOrEmpty(input.Materialname), u => EF.Functions.Like(u.MaterialName, $"%{input.Materialname.Trim()}%"))
// .Where(!string.IsNullOrEmpty(input.Materialspec), u => EF.Functions.Like(u.MaterialSpec, $"%{input.Materialspec.Trim()}%"))
// .Where(input.Inspectionmethod != null, u => u.InspectionMethod == input.Inspectionmethod)
// .Where(input.Unittype != null, u => u.UnitType == input.Unittype)
// .Where(input.Unitno != null, u => u.UnitNo == input.Unitno)
// .Where(u => u.StockNumber != 0)
// .Where(!string.IsNullOrEmpty(input.Placecode), u =0> u.PlaceCode == input.Placecode)
// .Where(!string.IsNullOrEmpty(input.Containercode), u => u.ContainerCode == input.Containercode)
// .OrderBy(PageInputOrder.OrderBuilder(input))
// .ProjectToType()
// .ToADPagedListAsync(input.PageNo, input.PageSize);
//获取登录用户
var contextUser = App.User;
var userName = contextUser.Claims.Single(x => x.Type == "Account").Value;
//获取登录用户所属线别
var lineType = await _sysUser.DetachedEntities.Where(u => u.Account == userName).Select(u => u.LineType).FirstOrDefaultAsync();
var lvms = await _v_ware_inventory_by_container.DetachedEntities
.Where(!string.IsNullOrEmpty(input.Materialno), u => u.WareMaterialCode.Contains(input.Materialno))
.Where(!string.IsNullOrEmpty(input.Materialname), u => u.WareMaterialName.Contains(input.Materialname))
.Where(!string.IsNullOrEmpty(input.Placecode), u => u.WareLocationCode == input.Placecode)
.Where(!string.IsNullOrEmpty(input.Containercode), u => u.WareContainerCode == input.Containercode)
.Where(!string.IsNullOrEmpty(input.PartCode), u => u.PartCode == input.PartCode)
.Where(!string.IsNullOrEmpty(input.PCPartCode), u => u.PartCode.Contains(input.PCPartCode))
.Where(lineType != null && lineType != LineTypeEnum.通用,u => u.LineType == lineType)
.OrderBy(PageInputOrder.OrderBuilder(input))
.ProjectToType()
.ToADPagedListAsync(input.PageNo, input.PageSize);
return lvms;
}
///
/// 手动出库
///
///
///
[HttpPost("ManualWare")]
public async Task ManualWare(ExManualWarehouseInput input)
{
if (string.IsNullOrEmpty(input.ToPlace))
{
throw Oops.Oh("目标站台不能为空");
}
if (string.IsNullOrEmpty(input.Containercode))
{
throw Oops.Oh("小车编号不能为空");
}
if (string.IsNullOrEmpty(input.Placecode))
{
throw Oops.Oh("库位编号不能为空");
}
//找库存
var balance = await _v_ware_inventory_by_container.DetachedEntities.Where(u => u.WareLocationCode == input.Placecode && u.WareContainerCode == input.Containercode && u.IsLocked == false).OrderBy(u => u.DeepcellNo).FirstOrDefaultAsync();
if (balance == null)
{
throw Oops.Oh($"根据小车{input.Containercode}和库位{input.Placecode}没有找到可用库存");
}
if (balance.StockStatus != StockStatusEnum.在库)
{
throw Oops.Oh($"零件{input.Containercode}对应的端拾器{input.Placecode}没有可用库存");
}
if (string.IsNullOrEmpty(input.ToPlace))
{
throw Oops.Oh("目的地不能为空");
}
var line = (LineTypeEnum)Enum.Parse(typeof(LineTypeEnum), input.ToPlace);
var site = await _wareSite.DetachedEntities.Where(u => u.LineType == line).FirstOrDefaultAsync();
if (site == null)
{
throw Oops.Oh("生产线没有配置站台");
}
// 创建任务
var tasknew = new WareTask
{
//OrderNo = input.OrderNo,
TaskNo = Yitter.IdGenerator.YitIdHelper.NextId().ToString(),
//TaskName = wcsTask.TaskName,
//TaskCategory = wcsTask.TaskType,
TaskCategory = TaskCategoryEnum.出库任务,
TaskDescribe = "",
TaskPriority = 99,
//TaskState = 0,
TaskState = (int)TaskStateEnum.未执行,
//TaskType = wcsTask.TaskType,
FromLocationCode = balance.WareLocationCode,
ToLocationCode = site.Code,
ContainerCode = balance.WareContainerCode,
Lane = balance.Lane,
ContainerType = 0,
PartCode = input.PartCode,
BeginTime = DateTimeOffset.Now,
};
var cvms = await _wmsContainerPlaceRep.Where(u => u.WareContainerCode == balance.WareContainerCode).ToListAsync();
foreach (var item in cvms)
{
item.StockStatus = StockStatusEnum.出库中;
item.IsLocked = true;
}
using (var tran = await _wareTask.Database.BeginTransactionAsync())
{
try
{
if (tasknew != null)
{
await _wareTask.InsertAsync(tasknew);
}
if (cvms != null && cvms.Count > 0)
{
await _wmsContainerPlaceRep.UpdateAsync(cvms);
}
await tran.CommitAsync();
}
catch
{
await tran.RollbackAsync();
}
}
}
///
/// 自动出库
///
///
///
[HttpPost("AutoWare")]
[AllowAnonymous]
public async Task AutoWare(ExAutoWarehouseInput input)
{
LineTypeEnum? lineType = null;
if (input.LineType == null)
{
var contextUser = App.User;
var userName = contextUser.Claims.Single(x => x.Type == "Account").Value;
//获取登录用户所属线别
lineType = await _sysUser.DetachedEntities.Where(u => u.Account == userName).Select(u => u.LineType).FirstOrDefaultAsync();
}
else
{
lineType = input.LineType;
}
////获取登录用户
//通过线别获取终点站台
if (lineType == null)
{
throw Oops.Oh("该登录用户没有配置线别");
}
//通过零件号查找端拾器信息
var part = await _wmsPart.DetachedEntities.Where(u => u.PartCode == input.PartNo && u.LineType == lineType).FirstOrDefaultAsync();
if (part == null && input.LineType == null)
{
throw Oops.Oh("生产线没有该零件信息");
}
LineTypeEnum? line = null;
if (input.LineType != null)
{
line = (LineTypeEnum)Enum.Parse(typeof(LineTypeEnum), Convert.ToString(input.LineType));
if (line != LineTypeEnum.A线 && line != LineTypeEnum.B线 && line != LineTypeEnum.C线)
{
throw Oops.Oh("请输入正确的线别");
}
}
var site = await _wareSite.Where(u => u.LineType == (line != null ? line : lineType)).FirstOrDefaultAsync();
if (site == null)
{
throw Oops.Oh($"线别{part.LineType}没有配置站台信息");
}
//找库存
var balance = await _v_ware_inventory_by_container.DetachedEntities.Where(u => u.PartCode == input.PartNo && u.WareMaterialCode == part.MaterialCode && u.IsLocked == false).OrderBy(u => u.DeepcellNo).FirstOrDefaultAsync();
if (balance == null)
{
throw Oops.Oh($"零件{input.PartNo}对应的端拾器没有可用库存");
}
if (balance.StockStatus != StockStatusEnum.在库)
{
throw Oops.Oh($"零件{input.PartNo}对应的端拾器没有可用库存");
}
// 创建任务
var tasknew = new WareTask
{
//OrderNo = input.OrderNo,
TaskNo = Yitter.IdGenerator.YitIdHelper.NextId().ToString(),
//TaskName = wcsTask.TaskName,
//TaskCategory = wcsTask.TaskType,
TaskCategory = TaskCategoryEnum.出库任务,
TaskDescribe = "",
TaskPriority = 99,
//TaskState = 0,
TaskState = (int)TaskStateEnum.未执行,
//TaskType = wcsTask.TaskType,
FromLocationCode = balance.WareLocationCode,
ToLocationCode = site.Code,
ContainerCode = balance.WareContainerCode,
Lane = balance.Lane,
ContainerType = 0,
PartCode = input.PartNo,
BeginTime = DateTimeOffset.Now,
};
var cvms = await _wmsContainerPlaceRep.Where(u => u.WareContainerCode == balance.WareContainerCode).ToListAsync();
foreach (var item in cvms)
{
item.StockStatus = StockStatusEnum.出库中;
item.IsLocked = true;
}
using (var tran = await _wareTask.Database.BeginTransactionAsync())
{
try
{
if (tasknew != null)
{
await _wareTask.InsertAsync(tasknew);
}
if (cvms != null && cvms.Count > 0)
{
await _wmsContainerPlaceRep.UpdateAsync(cvms);
}
await tran.CommitAsync();
}
catch
{
await tran.RollbackAsync();
}
}
}
///
/// 入库
///
///
///
[HttpPost("AutoInWare")]
[AllowAnonymous]
public async Task AutoInWare(ExAutoWarehouseInput input)
{
if (string.IsNullOrEmpty(input.RealLocationCode))
{
//throw Oops.Oh("目标库位不能为空");
//如果库位是空的,重新找一下库位
FindEmptyLocationServiceHandle handle = null;
handle = FindEmptyLocationServiceFactory.GetHandle(MeterialType.物料, _v_EmptyLocationRep,
_wmsPlaceRep,
_wareTask,
_wmsContainerPlaceRep,
_wmsContainerRep,
_wmsContainerType,
_v_ware_inventory_by_container,
input.RealLocationCode,
"");
var emtpyLocation = handle.MainFindEmptyLocation();
if (emtpyLocation == null)
{
throw Oops.Oh("目前没有空库位存放!");
}
input.RealLocationCode = emtpyLocation.PlaceCode;
}
else
{
var place = await _wmsPlaceRep.DetachedEntities.Where(u => u.PlaceCode == input.RealLocationCode).FirstOrDefaultAsync();
if (place == null)
{
throw Oops.Oh("目标库位不能是" + input.RealLocationCode);
}
var lvc = await _wareLocationVsContainer.DetachedEntities.Where(u => u.WareLocationCode == input.RealLocationCode).FirstOrDefaultAsync();
if (lvc != null)//目标有货
{
if (lvc.IsEmptyContainer == true)
{
throw Oops.Oh("配置的目标库位需要移库,请稍等");
}
else
{
throw Oops.Oh("目标库位有货,请处理");
}
}
input.RealLocationCode = place.PlaceCode;
}
////获取登录用户
//var contextUser = App.User;
//var userName = contextUser.Claims.Single(x => x.Type == "Account").Value;
////获取登录用户所属线别
//var lineType = await _sysUser.DetachedEntities.Where(u => u.Account == userName).Select(u => u.LineType).FirstOrDefaultAsync();
////通过线别获取终点站台
//if (lineType == null)
//{
// throw Oops.Oh("该登录用户没有配置线别");
//}
var vi = await _v_ware_inventory_by_container.DetachedEntities.Where(u => u.PartCode == input.PartCode && u.WareContainerCode == input.Containercode).FirstOrDefaultAsync();
if (vi == null)
{
throw Oops.Oh("没有查询到对应的信息");
}
if (vi.StockStatus == StockStatusEnum.在库)
{
throw Oops.Oh("对应端拾器已经在库");
}
//通过零件号查找端拾器信息
var part = await _wmsPart.DetachedEntities.Where(u => u.PartCode == vi.PartCode).FirstOrDefaultAsync();
if (part == null && input.LineType == null)
{
throw Oops.Oh("零件没有配置对应的端拾器信息");
}
LineTypeEnum? line = null;
if (input.ToPlace != null)
{
line = (LineTypeEnum)Enum.Parse(typeof(LineTypeEnum), Convert.ToString(input.ToPlace));
if (line != LineTypeEnum.A线 && line != LineTypeEnum.B线 && line != LineTypeEnum.C线)
{
throw Oops.Oh("请输入正确的线别");
}
}
var site = await _wareSite.Where(u => u.LineType == (line != null ? line : part.LineType)).FirstOrDefaultAsync();
if (site == null)
{
throw Oops.Oh($"线别{part.LineType}没有配置站台信息");
}
//找库存
//var balance = await _v_ware_inventory_by_container.DetachedEntities.Where(u => u.PartCode == input.PartNo && u.IsLocked == false).OrderBy(u => u.DeepcellNo).FirstOrDefaultAsync();
//if (balance == null)
//{
// throw Oops.Oh($"零件{input.PartNo}对应的端拾器没有可用库存");
//}
//if (balance.StockStatus != StockStatusEnum.在库)
//{
// throw Oops.Oh($"零件{input.PartNo}对应的端拾器没有可用库存");
//}
// 创建任务
var tasknew = new WareTask
{
//OrderNo = input.OrderNo,
TaskNo = Yitter.IdGenerator.YitIdHelper.NextId().ToString(),
//TaskName = wcsTask.TaskName,
//TaskCategory = wcsTask.TaskType,
TaskCategory = TaskCategoryEnum.入库任务,
TaskDescribe = "",
TaskPriority = 99,
//TaskState = 0,
TaskState = (int)TaskStateEnum.未执行,
//TaskType = wcsTask.TaskType,
FromLocationCode = site.Code,
ToLocationCode = input.RealLocationCode,
ContainerCode = vi.WareContainerCode,
Lane = vi.Lane,
ContainerType = 0,
PartCode = vi.PartCode,
BeginTime = DateTimeOffset.Now,
};
var cvms = await _wmsContainerPlaceRep.Where(u => u.WareContainerCode == vi.WareContainerCode).ToListAsync();
foreach (var item in cvms)
{
item.StockStatus = StockStatusEnum.出库中;
item.IsLocked = true;
}
using (var tran = await _wareTask.Database.BeginTransactionAsync())
{
try
{
if (tasknew != null)
{
await _wareTask.InsertAsync(tasknew);
}
if (cvms != null && cvms.Count > 0)
{
await _wmsContainerPlaceRep.UpdateAsync(cvms);
}
await tran.CommitAsync();
}
catch
{
await tran.RollbackAsync();
}
}
}
///
/// 获取移库空库位
///
///
///
[HttpGet("GetRemoveLocation")]
public async Task GetRemoveLocation([FromQuery] ExManualWarehouseInput input)
{
var container = await _wmsContainerRep.DetachedEntities.Where(u => u.ContainerCode == input.Containercode).FirstOrDefaultAsync();
if (container == null)
{
throw Oops.Oh("查询小车为空");
}
var containerType = await _wmsContainerType.DetachedEntities.Where(u => u.WareContainerTypeCode == container.ContainerTypeCode).FirstOrDefaultAsync();
if (containerType == null)
{
throw Oops.Oh("查询小车类型失败");
}
var location = await _v_empty_location.DetachedEntities.Where(u => u.WareLocationTypeCode == containerType.LocationType)
.Select(u => new { code = u.PlaceCode }).ToListAsync();
return location;
}
///
/// 手动移库任务
///
///
///
[HttpPost("MoveWare")]
public async Task MoveWare(ExManualWarehouseInput input)
{
if (string.IsNullOrEmpty(input.ToPlace))
{
throw Oops.Oh("目标站台不能为空");
}
if (string.IsNullOrEmpty(input.Containercode))
{
throw Oops.Oh("小车编号不能为空");
}
if (string.IsNullOrEmpty(input.Placecode))
{
throw Oops.Oh("库位编号不能为空");
}
var container = await _wmsContainerRep.Where(u => u.ContainerCode == input.Containercode).FirstOrDefaultAsync();
if (container == null)
{
throw Oops.Oh("查询小车为空");
}
var containerType = await _wmsContainerType.DetachedEntities.Where(u => u.WareContainerTypeCode == container.ContainerTypeCode).FirstOrDefaultAsync();
if (containerType == null)
{
throw Oops.Oh("查询小车类型失败");
}
var cvm = await _v_ware_inventory_by_container.DetachedEntities.Where(u => u.WareContainerCode == input.Containercode).FirstOrDefaultAsync();
if (cvm == null)
{
throw Oops.Oh("库存查询错误");
}
if (cvm.StockStatus != StockStatusEnum.在库)
{
throw Oops.Oh("库存不是在库");
}
var location = await _wmsPlaceRep.DetachedEntities.Where(u => u.PlaceCode == input.Placecode).FirstOrDefaultAsync();
if (location == null)
{
throw Oops.Oh("源库位查询错误");
}
if (location.WareLocationTypeCode != containerType.LocationType)
{
throw Oops.Oh("库位校验错误,选定的库位不是小车的可入库位");
}
if (location.DeepcellNo == (int)DeepcellNoEnum.远伸)
{
//选择库存远伸要判断一下近伸有没有货
var nearLocation = await _wmsPlaceRep.DetachedEntities.Where(u => u.UnionCode == location.UnionCode && u.DeepcellNo == (int)DeepcellNoEnum.近伸).FirstOrDefaultAsync();
if (nearLocation == null)
{
throw Oops.Oh("近伸库位查询错误");
}
var lvc = await _wareLocationVsContainer.DetachedEntities.Where(u => u.WareLocationCode == nearLocation.PlaceCode).FirstOrDefaultAsync();
if (lvc != null)
{
throw Oops.Oh("不能进行移库,因为选择的库存近伸有货");
}
}
var toLocation = await _v_empty_location.DetachedEntities.Where(u => u.PlaceCode == input.ToPlace).FirstOrDefaultAsync();
if (toLocation == null)
{
throw Oops.Oh("目标库位查询错误");
}
if (toLocation.DeepcellNo == DeepcellNoEnum.远伸)
{
//选择库存远伸要判断一下近伸有没有货
var nearLocation = await _v_empty_location.DetachedEntities.Where(u => u.UnionCode == toLocation.UnionCode && u.DeepcellNo == (int)DeepcellNoEnum.近伸).FirstOrDefaultAsync();
if (nearLocation == null)
{
throw Oops.Oh("近伸库位查询错误");
}
//var lvc = await _wareLocationVsContainer.DetachedEntities.Where(u => u.WareLocationCode == nearLocation.PlaceCode).FirstOrDefaultAsync();
//if (lvc != null)
//{
// throw Oops.Oh("不能进行移库,因为选择的目标库位近伸有货");
//}
toLocation = nearLocation;
}
//小车绑定库位更换
container.RealLocationCode = toLocation.PlaceCode;
// 创建任务
var tasknew = new WareTask
{
//OrderNo = input.OrderNo,
TaskNo = Yitter.IdGenerator.YitIdHelper.NextId().ToString(),
//TaskName = wcsTask.TaskName,
//TaskCategory = wcsTask.TaskType,
TaskCategory = TaskCategoryEnum.移库任务,
TaskDescribe = "",
TaskPriority = 99,
//TaskState = 0,
TaskState = (int)TaskStateEnum.未执行,
//TaskType = wcsTask.TaskType,
FromLocationCode = input.Placecode,
ToLocationCode = toLocation.PlaceCode,
ContainerCode = input.Containercode,
Lane = location.Line,
ContainerType = 0,
PartCode = input.PartCode,
BeginTime = DateTimeOffset.Now,
};
var cvms = await _wmsContainerPlaceRep.Where(u => u.WareContainerCode == input.Containercode).ToListAsync();
foreach (var item in cvms)
{
item.StockStatus = StockStatusEnum.移库中;
item.IsLocked = true;
}
using (var tran = await _wareTask.Database.BeginTransactionAsync())
{
try
{
if (tasknew != null)
{
await _wareTask.InsertAsync(tasknew);
}
if (cvms != null && cvms.Count > 0)
{
await _wmsContainerPlaceRep.UpdateAsync(cvms);
}
await _wmsContainerRep.UpdateAsync(container);
await tran.CommitAsync();
}
catch
{
await tran.RollbackAsync();
}
}
}
}
}