422 lines
16 KiB
C#
422 lines
16 KiB
C#
using AutoMapper;
|
|||
|
|
using JSMachine.WMS.App.Dto;
|
||
|
|
using JSMachine.WMS.App.Dto.Enum;
|
||
|
|
using JSMachine.WMS.App.IService;
|
||
|
|
using JSMachine.WMS.App.ServiceImpl;
|
||
|
|
using JSMachine.WMS.Application.Dto;
|
||
|
|
using JSMachine.WMS.Application.IService;
|
||
|
|
using JSMachine.WMS.Business.StockIn.IService;
|
||
|
|
using JSMachine.WMS.Business.StockIn.ServiceImpl.Strategy;
|
||
|
|
using JSMachine.WMS.Business.StockOut.IService;
|
||
|
|
using JSMachine.WMS.Domain.Entity;
|
||
|
|
using JSMachine.WMS.Domain.Entity.Enums;
|
||
|
|
using JSMachine.WMS.Infrastructure.Helper;
|
||
|
|
using JSMachine.WMS.RPC.ErpRPC.Dto.In.XRBusinessResult;
|
||
|
|
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
|
||
|
|
using JSMachine.WMS.WebHost.Models;
|
||
|
|
using Microsoft.AspNetCore.Mvc;
|
||
|
|
using Newtonsoft.Json;
|
||
|
|
using Org.BouncyCastle.Utilities.IO.Pem;
|
||
|
|
using SqlSugar;
|
||
|
|
using System.Linq.Expressions;
|
||
|
|
|
||
|
|
namespace JSMachine.WMS.WebHost.Controllers
|
||
|
|
{
|
||
|
|
[Route("api/[controller]/[action]")]
|
||
|
|
public class WarehouseController : ControllerBase
|
||
|
|
{
|
||
|
|
private IStorageRackService _storageRackService;
|
||
|
|
private IStockOutService _stockOutService;
|
||
|
|
private IERPTaskService _erpTaskService;
|
||
|
|
private IAGVTaskService _agvTaskService;
|
||
|
|
private IOperationLogService _operationLogService;
|
||
|
|
private IMapper _mapper;
|
||
|
|
|
||
|
|
public WarehouseController(
|
||
|
|
IStorageRackService storageRackService,
|
||
|
|
IStockOutService stockOutService,
|
||
|
|
IERPTaskService erpTaskService,
|
||
|
|
IAGVTaskService agvTaskService,
|
||
|
|
IOperationLogService operationLogService,
|
||
|
|
IMapper mapper
|
||
|
|
)
|
||
|
|
{
|
||
|
|
_storageRackService = storageRackService;
|
||
|
|
_stockOutService = stockOutService;
|
||
|
|
_erpTaskService = erpTaskService;
|
||
|
|
_agvTaskService = agvTaskService;
|
||
|
|
_operationLogService = operationLogService;
|
||
|
|
_mapper = mapper;
|
||
|
|
}
|
||
|
|
|
||
|
|
#region 库位维护
|
||
|
|
[HttpPost]
|
||
|
|
public async Task<ApiResult<bool>> UpdateWarehouseStatus(Guid id, bool isLocked)
|
||
|
|
{
|
||
|
|
//_ = _operationLogService.Add(new OperationLogDto
|
||
|
|
//{
|
||
|
|
// OperationSource = OperationSource.WEB,
|
||
|
|
// OperationType = OperationType.UpdateStorageRack,
|
||
|
|
// NewObject = $"StorageRackId:{id},IsLocked:{isLocked}",
|
||
|
|
// UserId=
|
||
|
|
//});
|
||
|
|
|
||
|
|
bool bRet = await _storageRackService.UpdateLockStatus(id, isLocked);
|
||
|
|
return new ApiResult<bool> { ResultCode = "200", Data = bRet };
|
||
|
|
}
|
||
|
|
|
||
|
|
[HttpPost]
|
||
|
|
public async Task<ApiResult<bool>> UpdateWarehouseDisableStatus(Guid id, bool isDisabled)
|
||
|
|
{
|
||
|
|
HttpContext.Request.Headers.TryGetValue("UserId", out var userIdValues);
|
||
|
|
|
||
|
|
_ = _operationLogService.Add(new OperationLogDto
|
||
|
|
{
|
||
|
|
OperationSource = OperationSource.WEB,
|
||
|
|
OperationType = OperationType.UpdateStorageRack,
|
||
|
|
NewObject = $"StorageRackId:{id},IsDisabled:{isDisabled}",
|
||
|
|
UserId = userIdValues
|
||
|
|
});
|
||
|
|
|
||
|
|
bool bRet = await _storageRackService.UpdateDisableStatus(id, isDisabled);
|
||
|
|
return new ApiResult<bool> { ResultCode = "200", Data = bRet };
|
||
|
|
}
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
[HttpPost]
|
||
|
|
public async Task<ApiResult<List<StorageRackDto>>> GetStorageRackLst(FloorEnum floor)
|
||
|
|
{
|
||
|
|
List<StorageRackDto> storageRack = new();
|
||
|
|
if (floor == 0)
|
||
|
|
{
|
||
|
|
storageRack = await _storageRackService.GetAll();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
storageRack = await _storageRackService.GetListByExpression(p => p.Floor == floor);
|
||
|
|
}
|
||
|
|
|
||
|
|
return new ApiResult<List<StorageRackDto>>() { ResultCode = "200", Data = storageRack };
|
||
|
|
}
|
||
|
|
|
||
|
|
[HttpPost]
|
||
|
|
public async Task<ApiResult<List<WareHouseAreaInfo>>> GetWareHouseAreaInfo(FloorEnum floor)
|
||
|
|
{
|
||
|
|
List<StorageRackDto> storageRacks = await _storageRackService.GetListByExpression(p => p.Floor == floor);
|
||
|
|
if (storageRacks.IsNullOrEmpty())
|
||
|
|
return new ApiResult<List<WareHouseAreaInfo>>();
|
||
|
|
|
||
|
|
storageRacks = storageRacks.OrderBy(p => p.ReservoirAreaColumnId).ThenBy(p => p.NumSort).ToList();
|
||
|
|
|
||
|
|
List<WareHouseAreaInfo> wareHouseAreaInfos = new();
|
||
|
|
var stockAreaGroups = storageRacks.GroupBy(p => p.ReservoirAreaId);
|
||
|
|
foreach (var areaGroup in stockAreaGroups)
|
||
|
|
{
|
||
|
|
var stockColGroup = areaGroup.GroupBy(p => p.ReservoirAreaColumnId);
|
||
|
|
WareHouseAreaInfo wareHouseAreaInfo = new()
|
||
|
|
{
|
||
|
|
AreaId = (int)areaGroup.Key.Value,
|
||
|
|
AreaName = areaGroup.First().StorageRackName,
|
||
|
|
};
|
||
|
|
|
||
|
|
List<WareHouseColumnInfo> Columns = new();
|
||
|
|
foreach (var colGroup in stockColGroup)
|
||
|
|
{
|
||
|
|
WareHouseColumnInfo wareHouseColumnInfo = new()
|
||
|
|
{
|
||
|
|
ColId = (int)colGroup.Key,
|
||
|
|
StorageRacks = colGroup.ToList()
|
||
|
|
};
|
||
|
|
|
||
|
|
Columns.Add(wareHouseColumnInfo);
|
||
|
|
}
|
||
|
|
|
||
|
|
wareHouseAreaInfo.Columns = Columns;
|
||
|
|
wareHouseAreaInfos.Add(wareHouseAreaInfo);
|
||
|
|
}
|
||
|
|
|
||
|
|
return new ApiResult<List<WareHouseAreaInfo>> { ResultCode = "200", Data = wareHouseAreaInfos };
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 根据库位查询物料信息
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="wareHouse"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
[HttpPost]
|
||
|
|
public async Task<ApiResult<StorageRackDto>> QueryMaterialInfo(string wareHouse)
|
||
|
|
{
|
||
|
|
StorageRackDto storageRack = await _storageRackService.GetSingalByExpression(p => p.StorageRackNo == wareHouse);
|
||
|
|
return new ApiResult<StorageRackDto>
|
||
|
|
{
|
||
|
|
ResultCode = "200",
|
||
|
|
Data = storageRack
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
[HttpPost]
|
||
|
|
public async Task<ApiResult<bool>> Update([FromBody] StorageRackDto storageRack)
|
||
|
|
{
|
||
|
|
HttpContext.Request.Headers.TryGetValue("UserId", out Microsoft.Extensions.Primitives.StringValues userIdValues);
|
||
|
|
_ = _operationLogService.Add(new OperationLogDto
|
||
|
|
{
|
||
|
|
OperationSource = string.IsNullOrEmpty(userIdValues) ? OperationSource.PDA : OperationSource.WEB,
|
||
|
|
OperationType = OperationType.UpdateStorageRack,
|
||
|
|
NewObject = JsonConvert.SerializeObject(storageRack),
|
||
|
|
UserId = userIdValues
|
||
|
|
});
|
||
|
|
|
||
|
|
bool bRet = await _storageRackService.EditSingal(storageRack);
|
||
|
|
|
||
|
|
return new ApiResult<bool>
|
||
|
|
{
|
||
|
|
ResultCode = bRet ? "200" : "500",
|
||
|
|
Data = bRet
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 查询入库物料已上传erp的数量
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="barcode"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
[HttpPost]
|
||
|
|
public async Task<ApiResult<int>> QueryUploadErpNum(string barCode)
|
||
|
|
{
|
||
|
|
ERPTaskDto erpTask = await _erpTaskService.GetSingalByExpression(p =>
|
||
|
|
p.BarCode == barCode &&
|
||
|
|
p.TaskType == TaskTypeEnum.PdaIn &&
|
||
|
|
p.TaskStatus == TaskStatusEnum.Completed);
|
||
|
|
|
||
|
|
return new ApiResult<int>
|
||
|
|
{
|
||
|
|
ResultCode = "200",
|
||
|
|
Data = erpTask == null ? 0 : erpTask.AlreadyUploadNum
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 获取今日入库明细
|
||
|
|
/// </summary>
|
||
|
|
/// <returns></returns>
|
||
|
|
[HttpGet]
|
||
|
|
public async Task<ApiResult<List<StockInDetail>>> GetStockinDetailToday(string elvatorStockinNo)
|
||
|
|
{
|
||
|
|
List<ERPTaskDto> erpTasksToday = await _erpTaskService.GetListByExpression(p =>
|
||
|
|
p.CreationTime > DateTime.Now.Date &&
|
||
|
|
(p.TaskType == TaskTypeEnum.PdaIn || p.TaskType == TaskTypeEnum.TailIn));
|
||
|
|
if (erpTasksToday.IsNullOrEmpty())
|
||
|
|
{
|
||
|
|
return new ApiResult<List<StockInDetail>> { Data = [], ResultCode = "200" };
|
||
|
|
}
|
||
|
|
|
||
|
|
List<AGVTaskDto> agvTasks = await _agvTaskService.GetListByExpression(p => erpTasksToday.Select(x => x.Id).Contains(p.ErpTaskId));
|
||
|
|
if(agvTasks.IsNullOrEmpty())
|
||
|
|
{
|
||
|
|
return new ApiResult<List<StockInDetail>> { Data = [], ResultCode = "200" };
|
||
|
|
}
|
||
|
|
|
||
|
|
List<StorageRackDto> storageRacks=await _storageRackService.GetAll();
|
||
|
|
if(storageRacks.IsNullOrEmpty())
|
||
|
|
return new ApiResult<List<StockInDetail>> { Data = [], ResultCode = "200" };
|
||
|
|
|
||
|
|
var agvTaskGroup = agvTasks.GroupBy(p=>p.ErpTaskId);
|
||
|
|
|
||
|
|
List<StockInDetail> stockInDetails = new();
|
||
|
|
|
||
|
|
foreach (var group in agvTaskGroup)
|
||
|
|
{
|
||
|
|
List<AGVTaskDto> agvTaskThisGroup = group.ToList();
|
||
|
|
List<StorageRackDto> endPositionThisGroup = storageRacks
|
||
|
|
.Where(p => agvTaskThisGroup.Select(x => x.EndPositionCode).Contains(p.StorageRackNo))
|
||
|
|
.ToList();
|
||
|
|
|
||
|
|
StorageRackDto storagerack = endPositionThisGroup.FirstOrDefault(p=>p.Transport==TransportEnum.NormalArea);
|
||
|
|
if(storagerack==null)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
if (string.IsNullOrEmpty(elvatorStockinNo))
|
||
|
|
{
|
||
|
|
StockInDetail stockInDetail = _mapper.Map<ERPTaskDto, StockInDetail>(
|
||
|
|
erpTasksToday.First(p => p.Id == agvTaskThisGroup.First().ErpTaskId));
|
||
|
|
|
||
|
|
stockInDetail.StoragePosition = storagerack.StorageRackNo;
|
||
|
|
stockInDetails.Add(stockInDetail);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
AGVTaskDto agvTask = agvTaskThisGroup.FirstOrDefault(p=>p.StartPositionCode== elvatorStockinNo);
|
||
|
|
if(agvTask==null)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
StockInDetail stockInDetail = _mapper.Map<ERPTaskDto, StockInDetail>(
|
||
|
|
erpTasksToday.First(p => p.Id == agvTaskThisGroup.First().ErpTaskId));
|
||
|
|
|
||
|
|
stockInDetail.StoragePosition = storagerack.StorageRackNo;
|
||
|
|
stockInDetails.Add(stockInDetail);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
stockInDetails = stockInDetails.OrderBy(p=>p.StoragePosition).ToList();
|
||
|
|
|
||
|
|
return new ApiResult<List<StockInDetail>>
|
||
|
|
{
|
||
|
|
Data = stockInDetails,
|
||
|
|
ResultCode = "200"
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
#region 搬运物料
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 物料搬运,起点库位验证
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="startRankNo"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
[HttpPost]
|
||
|
|
public async Task<ApiResult<string>> CheckCarryStartRankNo(string startRankNo)
|
||
|
|
{
|
||
|
|
return await _stockOutService.CheckCarryStartRankNo(startRankNo);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 物料搬运,起点库位验证
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="endRankNo"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
[HttpPost]
|
||
|
|
public async Task<ApiResult<string>> CheckCarryEndRankNo(string endRankNo)
|
||
|
|
{
|
||
|
|
return await _stockOutService.CheckCarryEndRankNo(endRankNo);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 搬运物料
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="erpSaleOutParam"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
[HttpPost]
|
||
|
|
public async Task<ApiResult<string>> CarryMaterial([FromBody] CarryInParam carryInParam)
|
||
|
|
{
|
||
|
|
LogHelper.Info($"收到PDA搬运物料请求,提交信息\n {JsonConvert.SerializeObject(carryInParam)}");
|
||
|
|
|
||
|
|
HttpContext.Request.Headers.TryGetValue("UserId", out var userIdValues);
|
||
|
|
_ = _operationLogService.Add(new OperationLogDto
|
||
|
|
{
|
||
|
|
OperationSource = OperationSource.PDA,
|
||
|
|
OperationType = OperationType.Carry,
|
||
|
|
NewObject = JsonConvert.SerializeObject(carryInParam),
|
||
|
|
UserId = userIdValues
|
||
|
|
});
|
||
|
|
|
||
|
|
return await _stockOutService.CarryMaterialInfo(carryInParam);
|
||
|
|
}
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region 出库码头维护
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 清空出库码头
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="transport"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
[HttpPost]
|
||
|
|
public async Task<ApiResult<bool>> ClearWharf(TransportEnum transport)
|
||
|
|
{
|
||
|
|
if (!(transport == TransportEnum.NorthArea || transport == TransportEnum.SouthArea || transport == TransportEnum.MiddleOutArea))
|
||
|
|
{
|
||
|
|
return new ApiResult<bool> { ResultCode = "500", Data = false, ErrorMsg = "码头编号错误" };
|
||
|
|
}
|
||
|
|
|
||
|
|
LogHelper.Info($"收到pda清空出库码头请求,码头类型 {transport.ToString()}");
|
||
|
|
|
||
|
|
List<StorageRackDto> storageRacks = await _storageRackService.GetListByExpression(p => p.Transport == transport);
|
||
|
|
storageRacks?.ForEach(p => { p.IsLock = false; p.BarCode = null; });
|
||
|
|
|
||
|
|
await _storageRackService.EditBatch(storageRacks);
|
||
|
|
|
||
|
|
return new ApiResult<bool> { ResultCode = "200", Data = true };
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 解锁南区码头
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="storageRack"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
[HttpPost]
|
||
|
|
public async Task<ApiResult<string>> UnlockSourthStorageRack()
|
||
|
|
{
|
||
|
|
LogHelper.Info($"收到PDA解锁南区码头库位请求");
|
||
|
|
var bRet = new ApiResult<string>() { ResultCode = "500", ErrorMsg = "解锁南区码头失败" };
|
||
|
|
|
||
|
|
var dataList = await _storageRackService.GetListByExpression(p => p.Transport == TransportEnum.SouthArea);
|
||
|
|
if (dataList != null && dataList.Count > 0)
|
||
|
|
{
|
||
|
|
foreach (var data in dataList)
|
||
|
|
{
|
||
|
|
data.IsLock = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
var result = await _storageRackService.EditBatch(dataList);
|
||
|
|
if (result)
|
||
|
|
{
|
||
|
|
bRet.ResultCode = "200";
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
bRet.ErrorMsg = "解锁南区码头:数据库操作失败";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return bRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 解锁北区码头
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="storageRack"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
[HttpPost]
|
||
|
|
public async Task<ApiResult<string>> UnlockNorthAreaStorageRack()
|
||
|
|
{
|
||
|
|
LogHelper.Info($"收到PDA解锁北区码头库位请求");
|
||
|
|
var bRet = new ApiResult<string>() { ResultCode = "500", ErrorMsg = "解锁北区码头失败" };
|
||
|
|
|
||
|
|
var dataList = await _storageRackService.GetListByExpression(p => p.Transport == TransportEnum.NorthArea);
|
||
|
|
if (dataList != null && dataList.Count > 0)
|
||
|
|
{
|
||
|
|
foreach (var data in dataList)
|
||
|
|
{
|
||
|
|
data.IsLock = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
var result = await _storageRackService.EditBatch(dataList);
|
||
|
|
if (result)
|
||
|
|
{
|
||
|
|
bRet.ResultCode = "200";
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
bRet.ErrorMsg = "解锁北区码头:数据库操作失败";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return bRet;
|
||
|
|
}
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region 物料查询
|
||
|
|
[HttpPost]
|
||
|
|
public async Task<ApiResult<List<StorageRackDto>>> GetMaterialInfo([FromBody] MaterialQueryParam materialQueryParam)
|
||
|
|
{
|
||
|
|
Expression<Func<StorageRackDto, bool>> express = materialQueryParam.BuildExpress();
|
||
|
|
List<StorageRackDto> storageRacks = await _storageRackService.GetListByExpression(express);
|
||
|
|
|
||
|
|
storageRacks = storageRacks?.OrderBy(p=>p.Floor).ThenBy(p=>p.AreaNumSort).ThenBy(p=>p.ReservoirAreaColumnId).ThenBy(p=>p.NumSort).ToList();
|
||
|
|
|
||
|
|
return new ApiResult<List<StorageRackDto>>() { ResultCode = "200", Data = storageRacks };
|
||
|
|
|
||
|
|
}
|
||
|
|
#endregion
|
||
|
|
}
|
||
|
|
}
|