first commit

This commit is contained in:
2026-09-02 16:31:50 +08:00
commit a461727193
911 changed files with 692450 additions and 0 deletions
@@ -0,0 +1,147 @@
using JSMachine.WMS.App.Dto;
using JSMachine.WMS.App.Dto.Enum;
using JSMachine.WMS.App.IService;
using JSMachine.WMS.Business.RcsCallBack.IService;
using JSMachine.WMS.Common.Dto.Business;
using JSMachine.WMS.Infrastructure.Helper;
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
using Microsoft.AspNetCore.Mvc;
using NLog.Web.LayoutRenderers;
using NPOI.POIFS.Crypt.Agile;
using SqlSugar;
namespace JSMachine.WMS.WebHost.Controllers
{
[Route("api/[controller]/[action]")]
/// <summary>
/// 提供 AGV 任务查询和报警处理相关的 HTTP 接口。
/// </summary>
public class AgvTaskController : ControllerBase
{
private IAGVTaskService _agvTaskService;
private IRcsCallBackService _rcsCallBackService;
/// <summary>创建 AGV 任务控制器。</summary>
/// <param name="agvTaskService">AGV 任务查询服务。</param>
/// <param name="rcsCallBackService">RCS 回调及报警处理服务。</param>
public AgvTaskController(
IAGVTaskService agvTaskService,
IRcsCallBackService rcsCallBackService)
{
_agvTaskService = agvTaskService;
_rcsCallBackService = rcsCallBackService;
}
[HttpGet]
/// <summary>
/// 查询指定条件下最近创建的 AGV 任务。
/// </summary>
/// <returns>按创建时间倒序返回 AGV 任务列表。</returns>
public async Task<ApiResult<List<AGVTaskDto>>> GetAll()
{
List<AGVTaskDto> agvTaska = await _agvTaskService.GetListByExpression(p =>
p.Floor == 10 && p.TaskType == 2,
nameof(AGVTaskDto.CreationTime),
OrderByType.Desc);
return new ApiResult<List<AGVTaskDto>>
{
ResultCode = "200",
Data = agvTaska
};
}
[HttpPost]
/// <summary>查询指定 ERP 任务关联的 AGV 任务。</summary>
/// <param name="erpTaskId">ERP 任务标识。</param>
/// <returns>按创建时间升序返回关联任务。</returns>
public async Task<ApiResult<List<AGVTaskDto>>> GetAgvTasksRelatedToErpTask(Guid erpTaskId)
{
List<AGVTaskDto> agvTaska = await _agvTaskService.GetListByExpression(p =>
p.ErpTaskId == erpTaskId,nameof(AGVTaskDto.CreationTime),OrderByType.Asc);
return new ApiResult<List<AGVTaskDto>>
{
ResultCode = "200",
Data = agvTaska
};
}
/// <summary>
/// 获取所有agv小车报警信息
/// </summary>
/// <returns></returns>
[HttpGet]
public ApiResult<List<AgvTaskFailedAlarmInfo>> GetAlarmInfoes()
{
//return new ApiResult<List<AgvTaskFailedAlarmInfo>>
//{
// ResultCode="200",
// Data =
// [
// new AgvTaskFailedAlarmInfo{ AgvTaskId=Guid.NewGuid(),Operation="请把把托盘放到提升机入库口1"},
// new AgvTaskFailedAlarmInfo{AgvTaskId=Guid.NewGuid(),Operation="请把把托盘放到提升机入库口2" }
// ]
//};
return new ApiResult<List<AgvTaskFailedAlarmInfo>>
{
ResultCode = "200",
Data = GlobalAgvTaskFailedAlarmInfo.GetAlarmInfoes()
};
}
/// <summary>
/// 上传报警处理结果
/// </summary>
/// <param name="agvTaskId"></param>
/// <returns></returns>
[HttpPost]
public async Task<ApiResult<bool>> PostAlarmHandleResult(Guid agvTaskId)
{
LogHelper.Warn($"PDA上传报警处理,AgvTaskId {agvTaskId}");
bool bRet = await _rcsCallBackService.DealWithAlarmHandleResult(agvTaskId);
return new ApiResult<bool> { ResultCode = bRet ? "200" : "500", Data = bRet };
}
/// <summary>
/// 获取搬运物料的AgvTask
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<ApiResult<List<AGVTaskDto>>> GetCarryAgvTask()
{
List<AGVTaskDto> agvTaska = await _agvTaskService.GetListByExpression(p =>
p.TaskType == 6 && p.CreationTime >= DateTime.Now.AddHours(-4),
nameof(AGVTaskDto.CreationTime),
OrderByType.Desc);
return new ApiResult<List<AGVTaskDto>>
{
ResultCode = "200",
Data = agvTaska
};
}
/// <summary>
/// 判断是否重复入库(30分钟内同一库位存在入库任务,则弹窗提示二次确认)
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<ApiResult<bool>> IsReStockIn(string wareHouse)
{
bool exist = await _agvTaskService.Exist(p =>
p.CreationTime >= DateTime.Now.AddMinutes(-30) &&
p.StartPositionCode == wareHouse &&
(p.TaskType == TaskTypeEnum.PdaIn || p.TaskType == TaskTypeEnum.TailIn)
);
return new ApiResult<bool>
{
ResultCode="200",
Data=exist
};
}
}
}
@@ -0,0 +1,29 @@
using JSMachine.WMS.App.Dto;
using JSMachine.WMS.App.IService;
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
using Microsoft.AspNetCore.Mvc;
namespace JSMachine.WMS.WebHost.Controllers
{
[Route("api/[controller]/[action]")]
public class ElevatorCountController : ControllerBase
{
private IElevatorCountService _elevatorCountService;
public ElevatorCountController(IElevatorCountService elevatorCountService)
{
_elevatorCountService = elevatorCountService;
}
[HttpGet]
public async Task<ApiResult<List<ElevatorCountDto>>> GetElevatorCountToday()
{
List<ElevatorCountDto> elevatorCounts = await _elevatorCountService.GetListByExpression(p => p.CreationTime >= DateTime.Now.Date);
return new ApiResult<List<ElevatorCountDto>>
{
ResultCode = "200",
Data = elevatorCounts
};
}
}
}
@@ -0,0 +1,35 @@
using JSMachine.WMS.App.Dto;
using JSMachine.WMS.App.IService;
using JSMachine.WMS.App.ServiceImpl;
using JSMachine.WMS.Domain.Entity;
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
using Microsoft.AspNetCore.Mvc;
using Org.BouncyCastle.Crypto;
namespace JSMachine.WMS.WebHost.Controllers
{
[Route("api/[controller]/[action]")]
public class ElevatorQueController : ControllerBase
{
private IElevatorPlcQueueService _elevatorPlcQueueService;
public ElevatorQueController(IElevatorPlcQueueService elevatorPlcQueueService)
{
_elevatorPlcQueueService = elevatorPlcQueueService;
}
[HttpGet]
public async Task<ApiResult<List<ElevatorPlcQueueDto>>> GetElevatorQueToday()
{
List<ElevatorPlcQueueDto> elevatorPlcQueues = await _elevatorPlcQueueService.GetListByExpression(p =>
p.CreationTime >= DateTime.Now.Date &&
(p.ElevatorChannel == 1001 || p.ElevatorChannel == 1011));
return new ApiResult<List<ElevatorPlcQueueDto>>
{
ResultCode = "200",
Data = elevatorPlcQueues
};
}
}
}
@@ -0,0 +1,301 @@
using JSMachine.WMS.App.Dto;
using JSMachine.WMS.App.Dto.Enum;
using JSMachine.WMS.App.IService;
using JSMachine.WMS.Application.Dto;
using JSMachine.WMS.Application.IService;
using JSMachine.WMS.Business.StockIn.IService;
using JSMachine.WMS.Business.StockOut.IService;
using JSMachine.WMS.Domain.Entity;
using JSMachine.WMS.Domain.Entity.Enums;
using JSMachine.WMS.Infrastructure;
using JSMachine.WMS.Infrastructure.Helper;
using JSMachine.WMS.RPC.ErpRPC.Dto.In.XRBusinessResult;
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
using JSMachine.WMS.RPC.ErpRPC.Dto.Out.XRBusinessResult;
using JSMachine.WMS.RPC.ErpRPC.IService;
using JSMachine.WMS.WebHost.Models;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
namespace JSMachine.WMS.WebHost.Controllers
{
[Route("api/[controller]/[action]")]
public class ErpController : ControllerBase
{
private IStockInService _stockInByPdaService;
private IStockOutService _stockOutService;
private IERPTaskService _erpTaskService;
private IStorageRackService _storageRackService;
private IPaperStorageService _paperStorageService;
private IOperationLogService _operationLogService;
public ErpController(
IStockInService stockInByPdaService,
IStockOutService stockOutService,
IERPTaskService erpTaskService,
IStorageRackService storageRackService,
IPaperStorageService paperStorageService,
IOperationLogService operationLogService
)
{
_stockInByPdaService = stockInByPdaService;
_stockOutService = stockOutService;
_erpTaskService = erpTaskService;
_storageRackService = storageRackService;
_paperStorageService = paperStorageService;
_operationLogService = operationLogService;
}
[HttpGet]
public async Task<ApiResult<List<ERPTaskDto>>> GetLatestErpTasks(TaskTypeEnum taskType)
{
List<ERPTaskDto> erpTasks = await _erpTaskService
.GetListByExpression(p =>
p.LastModifiedTime >= DateTime.Now.Date &&
p.TaskType == taskType
);
erpTasks = erpTasks?.OrderByDescending(p => p.CreationTime).ToList();
return new ApiResult<List<ERPTaskDto>>
{
ResultCode = "200",
Data = erpTasks
};
}
/// <summary>
/// 条件查询erp任务
/// </summary>
/// <param name="startTime"></param>
/// <param name="endTime"></param>
/// <param name="taskType"></param>
/// <returns></returns>
[HttpPost]
public async Task<ApiResult<List<ERPTaskDto>>> GetErpTasks([FromBody]ErpTaskQueryParam erpTaskQueryParam)
{
List<ERPTaskDto> erpTasks = await _erpTaskService.GetListByExpression(p =>
p.CreationTime >= erpTaskQueryParam.StartTime &&
p.CreationTime <= erpTaskQueryParam.EndTime &&
(erpTaskQueryParam.TaskType == 0 ? true : p.TaskType == erpTaskQueryParam.TaskType),
"CreationTime", SqlSugar.OrderByType.Desc);
return new ApiResult<List<ERPTaskDto>>
{
ResultCode = "200",
Data = erpTasks
};
}
/// <summary>
/// 合格证号是否已存在
/// </summary>
/// <param name="barCode"></param>
/// <returns></returns>
[HttpPost]
public async Task<ApiResult<bool>> IsBarCodeExist(string barCode, TaskTypeEnum taskType)
{
bool exist = false;
if (taskType == TaskTypeEnum.PdaIn)
{
exist = await _erpTaskService.Exist(p =>
p.BarCode == barCode &&
(p.TaskStatus == TaskStatusEnum.Initial || p.TaskStatus == TaskStatusEnum.InExecution || p.TaskStatus == TaskStatusEnum.Completed) &&
p.TaskType == TaskTypeEnum.PdaIn
);
}
else if (taskType == TaskTypeEnum.TailIn)
{
exist = await _erpTaskService.Exist(p =>
p.CreationTime >= DateTime.Now.AddHours(-1) &&
p.BarCode == barCode &&
(p.TaskStatus == TaskStatusEnum.Initial || p.TaskStatus == TaskStatusEnum.InExecution || p.TaskStatus == TaskStatusEnum.Completed) &&
p.TaskType == TaskTypeEnum.TailIn
);
}
return new ApiResult<bool>
{
ResultCode = "200",
Data = exist
};
}
/// <summary>
/// 从erp获取物料信息
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<ApiResult<StorageRackDto>> GetMaterialInfoFromErp(string barCode)
{
XRResultDto erpResult = await _paperStorageService.GetMateriaInfo(barCode);
StorageRackDto storageRack = new();
if (erpResult != null && erpResult.data != null)
{
storageRack.BarCode = erpResult.data.BarCode;
storageRack.OrderNo = erpResult.data.OrderNo;
storageRack.MateriaName = erpResult.data.MateriaName;
storageRack.MateriaType = erpResult.data.MateriaType;
storageRack.MateriaNum = int.Parse(erpResult.data.MateriaNum);
storageRack.MateriaBatch = erpResult.data.MateriaBatch;
storageRack.MateriaCode = erpResult.data.MateriaCode;
}
return new ApiResult<StorageRackDto>
{
ResultCode = "200",
Data = storageRack
};
}
/// <summary>
/// 更新单个任务状态
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpPost]
public async Task<ApiResult<bool>> UpdateTaskStatus(Guid id, TaskStatusEnum taskStatus)
{
LogHelper.Info($"收到pda更新erp任务请求,任务id {id} 更新后的状态 {taskStatus}");
ERPTaskDto erpTask = await _erpTaskService.GetSingalByExpression(p => p.Id == id);
if (erpTask.TaskStatus != TaskStatusEnum.Initial)
{
LogHelper.Warn($"任务 {id} 当前状态已不是待下发状态,无法取消");
return new ApiResult<bool>
{
Data = false,
ResultCode = "500",
ErrorMsg = "所选择的任务当前已不是待下发状态,无法取消"
};
}
erpTask.TaskStatus = taskStatus;
bool bRet = await _erpTaskService.EditSingal(erpTask);
return new ApiResult<bool>
{
Data = bRet,
ResultCode = bRet ? "200" : "500"
};
}
/// <summary>
/// 任务操作
/// </summary>
/// <param name="id"></param>
/// <param name="taskStatus"></param>
/// <returns></returns>
[HttpPost]
public async Task<ApiResult<bool>> OperateTask(Guid id, TaskStatusEnum taskStatus)
{
LogHelper.Info($"收到网站更新erp任务请求,任务id {id} 更新后的状态 {taskStatus}");
HttpContext.Request.Headers.TryGetValue("UserId", out var userIdValues);
_ = _operationLogService.Add(new OperationLogDto
{
OperationSource = OperationSource.WEB,
OperationType = OperationType.UpdateErpTask,
NewObject = string.Format("ErpTaskId:{0},TaskStatus:{1}", id, taskStatus.GetDescription()),
UserId = userIdValues
});
ERPTaskDto erpTask = await _erpTaskService.GetSingalByExpression(p => p.Id == id);
if(erpTask==null)
{
return new ApiResult<bool>
{
Data=false,
ResultCode="500",
ErrorMsg="任务不存在,请刷新后再次重试"
};
}
erpTask.LastModifiedTime=DateTime.Now;
erpTask.TaskStatus = taskStatus;
bool bRet = await _erpTaskService.EditSingalWithSpecificCols(erpTask,[nameof(ERPTaskDto.LastModifiedTime),nameof(ERPTaskDto.TaskStatus)]);
return new ApiResult<bool>
{
Data = bRet,
ResultCode = bRet ? "200" : "500"
};
}
/// <summary>
/// 暂停所有待执行的任务
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<ApiResult<bool>> StopAll(TaskTypeEnum taskType)
{
LogHelper.Info("收到PDA暂停所有任务请求");
List<ERPTaskDto> erpTasks = await _erpTaskService.GetListByExpression(p =>
p.CreationTime > DateTime.Now.Date &&
p.TaskStatus == TaskStatusEnum.Initial &&
p.TaskType == taskType);
if (erpTasks.IsNullOrEmpty())
{
return new ApiResult<bool>
{
ResultCode = "200",
Data = true
};
}
erpTasks.ForEach(p => p.TaskStatus = TaskStatusEnum.Paused);
bool bRet = await _erpTaskService.EditBatch(erpTasks);
return new ApiResult<bool>
{
Data = bRet,
ResultCode = bRet ? "200" : "500"
};
}
/// <summary>
/// 恢复所有暂停的任务
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<ApiResult<bool>> ResumeAll(TaskTypeEnum taskType)
{
LogHelper.Info("收到PDA恢复所有任务请求");
List<ERPTaskDto> erpTasks = await _erpTaskService.GetListByExpression(p =>
p.CreationTime > DateTime.Now.Date &&
p.TaskStatus == TaskStatusEnum.Paused &&
p.TaskType == taskType);
if (erpTasks.IsNullOrEmpty())
{
return new ApiResult<bool>
{
ResultCode = "200",
Data = true
};
}
erpTasks.ForEach(p => p.TaskStatus = TaskStatusEnum.Initial);
bool bRet = await _erpTaskService.EditBatch(erpTasks);
return new ApiResult<bool>
{
Data = bRet,
ResultCode = bRet ? "200" : "500"
};
}
}
}
@@ -0,0 +1,138 @@
using JSMachine.WMS.App.Dto;
using JSMachine.WMS.Application.Dto;
using JSMachine.WMS.Application.IService;
using JSMachine.WMS.Domain.Entity;
using JSMachine.WMS.Infrastructure.Helper;
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
using JSMachine.WMS.WebHost.Models;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
namespace JSMachine.WMS.WebHost.Controllers
{
[Route("api/[controller]/[action]")]
public class OperationLogController : ControllerBase
{
private readonly IOperationLogService _operationLogService;
public OperationLogController(IOperationLogService operationLogService)
{
_operationLogService = operationLogService;
}
/// <summary>
/// 获取所有操作日志
/// </summary>
/// <returns>操作日志列表</returns>
[HttpGet]
public async Task<ApiResult<List<OperationLogDto>>> GetAll()
{
var logs = await _operationLogService.GetListByExpression(
p => true,
nameof(OperationLogDto.CreationTime),
OrderByType.Desc);
return new ApiResult<List<OperationLogDto>>
{
ResultCode = "200",
Data = logs
};
}
/// <summary>
/// 根据ID获取操作日志
/// </summary>
/// <param name="id">操作日志ID</param>
/// <returns>单个操作日志</returns>
[HttpPost]
public async Task<ApiResult<OperationLogDto>> GetById(Guid id)
{
var log = await _operationLogService.GetSingalByExpression(p => p.Id == id);
return new ApiResult<OperationLogDto>
{
ResultCode = "200",
Data = log
};
}
/// <summary>
/// 创建操作日志
/// </summary>
/// <param name="logDto">操作日志DTO</param>
/// <returns>是否创建成功</returns>
[HttpPost]
public async Task<ApiResult<bool>> Create(OperationLogDto logDto)
{
if (logDto == null)
return new ApiResult<bool> { ResultCode = "400", Data = false, ErrorMsg = "参数不能为空" };
bool success = await _operationLogService.Add(logDto);
return new ApiResult<bool>
{
ResultCode = success ? "200" : "500",
Data = success,
ErrorMsg = success ? "创建成功" : "创建失败"
};
}
/// <summary>
/// 更新操作日志
/// </summary>
/// <param name="logDto">操作日志DTO</param>
/// <returns>是否更新成功</returns>
[HttpPost]
public async Task<ApiResult<bool>> Update(OperationLogDto logDto)
{
if (logDto == null || logDto.Id == Guid.Empty)
return new ApiResult<bool> { ResultCode = "400", Data = false, ErrorMsg = "参数无效" };
bool success = await _operationLogService.EditSingal(logDto);
return new ApiResult<bool>
{
ResultCode = success ? "200" : "500",
Data = success,
ErrorMsg = success ? "更新成功" : "更新失败"
};
}
/// <summary>
/// 删除操作日志
/// </summary>
/// <param name="id">操作日志ID</param>
/// <returns>是否删除成功</returns>
[HttpPost]
public async Task<ApiResult<bool>> Delete(Guid id)
{
bool success = await _operationLogService.DeleteById(id);
return new ApiResult<bool>
{
ResultCode = success ? "200" : "500",
Data = success,
ErrorMsg = success ? "删除成功" : "删除失败"
};
}
/// <summary>
/// 分页查询操作日志
/// </summary>
/// <param name="pageQuery">分页查询条件</param>
/// <returns>分页结果</returns>
[HttpPost]
public async Task<ApiResult<PagedResult<OperationLogDto>>> QueryByPage([FromBody]OperationLogQueryParam pageQuery)
{
var condition = pageQuery.BuildConditional();
var result = await _operationLogService.QueryByPage(condition);
return new ApiResult<PagedResult<OperationLogDto>>
{
ResultCode = "200",
Data = result
};
}
}
}
@@ -0,0 +1,47 @@
using JSMachine.WMS.Business.SSE;
using Microsoft.AspNetCore.Mvc;
using System.Text;
namespace JSMachine.WMS.WebHost.Controllers
{
/// <summary>
/// 用于向前端网站推送消息
/// </summary>
[Route("api/sse")]
public class SseController: ControllerBase
{
[HttpGet("connect")]
public async Task Connect()
{
var response = Response;
response.Headers.Append("Content-Type", "text/event-stream");
response.Headers.Append("Cache-Control", "no-cache");
response.Headers.Append("Connection", "keep-alive");
// 记录客户端连接(用于后续推送消息)
ClientConnection client = new()
{
Response = response,
ClientId = Guid.NewGuid().ToString()
};
SseEngine.AddClient(client);
// 保持连接,直到客户端断开
while (!response.HttpContext.RequestAborted.IsCancellationRequested)
{
await Task.Delay(1000); // 防止 CPU 占用过高
}
// 客户端断开时移除
SseEngine.RemoveClient(client);
}
[HttpPost("send")]
public IActionResult SendMessage([FromBody] string message)
{
// 向所有连接的客户端推送消息
SseEngine.BrodCast(message);
return Ok();
}
}
}
@@ -0,0 +1,65 @@
using JSMachine.WMS.App.Dto.Enum;
using JSMachine.WMS.App.IService;
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
using JSMachine.WMS.WebHost.Models;
using Microsoft.AspNetCore.Mvc;
namespace JSMachine.WMS.WebHost.Controllers
{
[Route("api/[controller]/[action]")]
public class StatisticController: ControllerBase
{
private IStorageRackService _storageRackService;
private IAGVTaskService _agvTaskService;
private IERPTaskService _erptaskService;
public StatisticController(IStorageRackService storageRackService, IAGVTaskService agvTaskService, IERPTaskService erptaskService)
{
_storageRackService = storageRackService;
_agvTaskService = agvTaskService;
_erptaskService = erptaskService;
}
[HttpPost]
public async Task<ApiResult<StockInAndOutStatisticInfo>> GetStockInAndOutStatistic()
{
int stockInCount = await _erptaskService.Count(p =>
p.CreationTime > DateTime.Now.Date &&
(p.TaskType == TaskTypeEnum.PdaIn || p.TaskType == TaskTypeEnum.TailIn)
);
int stockOutCount = await _agvTaskService.Count(p =>
p.CreationTime > DateTime.Now.Date &&
(p.TaskType == TaskTypeEnum.SaleOut || p.TaskType == TaskTypeEnum.ProductionOut) &&
p.Floor == FloorEnum.FirstFloor
);
int allGoodsCount = await _storageRackService.Count(p =>
p.Floor == FloorEnum.SecondFloor &&
p.Transport == TransportEnum.NormalArea &&
!string.IsNullOrEmpty(p.BarCode)
);
int emptyStorageCount = await _storageRackService.Count(p =>
p.Floor == FloorEnum.SecondFloor &&
p.Transport == TransportEnum.NormalArea &&
string.IsNullOrEmpty(p.BarCode)
);
decimal storageRackeUsedRatio = (allGoodsCount) * 100m / (allGoodsCount+emptyStorageCount);
return new ApiResult<StockInAndOutStatisticInfo>
{
ResultCode="200",
Data = new StockInAndOutStatisticInfo
{
StockInCount = stockInCount,
StockOutCount = stockOutCount,
AllGoodsCount = allGoodsCount,
EmptyStorageCount = emptyStorageCount,
StorageRackeUsedRatio = Math.Floor(storageRackeUsedRatio)
}
};
}
}
}
@@ -0,0 +1,234 @@
using JSMachine.WMS.App.Dto;
using JSMachine.WMS.App.IService;
using JSMachine.WMS.App.ServiceImpl;
using JSMachine.WMS.Infrastructure.Helper;
using JSMachine.WMS.RPC.ErpRPC.Dto.In.XRBusinessResult;
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
using JSMachine.WMS.RPC.ErpRPC.Dto.Out.XRBusinessResult;
using JSMachine.WMS.RPC.RcsRPC.Dto.In;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Org.BouncyCastle.Asn1.Mozilla;
using System.Net;
namespace JSMachine.WMS.WebHost.Controllers
{
/// <summary>
/// 测试用控制器(模拟erp等服务)
/// </summary>
public class TestController : ControllerBase
{
private IRcsTaskService _rcsTaskService;
public TestController(IRcsTaskService rcsTaskService)
{
_rcsTaskService = rcsTaskService;
}
private static List<MateriaInfoDto> MateriaInfos = new()
{
new MateriaInfoDto{ BarCode="HZYD23053001730001",MateriaNum="600",MateriaCode="20230206003782",MateriaBatch="ZYD23053001732024-10-231",OrderNo="ZYD2305300173_0",MateriaName="220847达利250mlx12包x3盒花生牛奶条型原味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23053001730002",MateriaNum="600",MateriaCode="20230206003782",MateriaBatch="ZYD23053001732024-10-231",OrderNo="ZYD2305300173_0",MateriaName="220847达利250mlx12包x3盒花生牛奶条型原味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23053001730003",MateriaNum="600",MateriaCode="20230206003782",MateriaBatch="ZYD23053001732024-10-231",OrderNo="ZYD2305300173_0",MateriaName="220847达利250mlx12包x3盒花生牛奶条型原味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23053001730004",MateriaNum="600",MateriaCode="20230206003782",MateriaBatch="ZYD23053001732024-10-231",OrderNo="ZYD2305300173_0",MateriaName="220847达利250mlx12包x3盒花生牛奶条型原味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23053001730005",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD23060700682024-10-231",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23060700680001",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23060700680002",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23060700680003",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23060700680004",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23060700680005",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23060700680006",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23060700680007",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23060700680008",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23070700690001",MateriaNum="600",MateriaCode="20230206003784",MateriaBatch="ZYD25070900902025-07-142",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23070700690002",MateriaNum="600",MateriaCode="20230206003784",MateriaBatch="ZYD25070900902025-07-142",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23070700690003",MateriaNum="600",MateriaCode="20230206003784",MateriaBatch="ZYD25070900902025-07-142",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23070700690004",MateriaNum="600",MateriaCode="20230206003784",MateriaBatch="ZYD25070900902025-07-142",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23070700690005",MateriaNum="600",MateriaCode="20230206003784",MateriaBatch="ZYD25070900902025-07-142",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23070700690006",MateriaNum="600",MateriaCode="20230206003784",MateriaBatch="ZYD25070900902025-07-142",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23080800760001",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25040100142025-04-081",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23080800760002",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25040100142025-04-081",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23080800760003",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25040100142025-04-081",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23080800760004",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25040100142025-04-081",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23080800760005",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25040100142025-04-081",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23090800760001",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25010800682025-01-091",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23090800760002",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25010800682025-01-091",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23090800760003",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25010800682025-01-091",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23090800760004",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25010800682025-01-091",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23090800760005",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25010800682025-01-091",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
new MateriaInfoDto{ BarCode="HZYD23090800760006",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25010800682025-01-091",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_381_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_367_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_366_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_365_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_364_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_363_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_383_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_349_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_348_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
new MateriaInfoDto{ BarCode="HZYD25102702680174",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-171",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
new MateriaInfoDto{ BarCode="HZYD25102702680178",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-171",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
new MateriaInfoDto{ BarCode="HZYD25102702680173",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-171",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
new MateriaInfoDto{ BarCode="HZYD25102702680177",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-171",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_362_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
};
/// <summary>
/// 模拟erp提供查询物料信息服务
/// </summary>
/// <param name="barcodeInfo"></param>
/// <returns></returns>
[HttpPost]
[Route("wms_erp_interface/select/materiaInformation")]
public async Task<XRApiResult<XRResultDto>> QueryMateriaInfor([FromBody] dynamic barcodeInfo)
{
return new XRApiResult<XRResultDto>
{
id = Guid.NewGuid().ToString(),
jsonrpc = "",
result = new XRResultDto
{
status = 200,
data = MateriaInfos.FirstOrDefault(p => p.BarCode == barcodeInfo["barCode"].ToString()),
success = true
}.ToJson()
};
}
/// <summary>
/// 模拟erp提供入库上传接口
/// </summary>
/// <param name="barcodeInfo"></param>
/// <returns></returns>
[HttpPost]
[Route("wms_erp_interface/api/wms/produce/in")]
public async Task<XRApiResult<XRResultDto>> UploadStockIn([FromBody] dynamic barcodeInfo)
{
return new XRApiResult<XRResultDto>
{
id = Guid.NewGuid().ToString(),
jsonrpc = "",
result = new XRResultDto
{
status = 200,
success = true
}.ToJson()
};
}
/// <summary>
/// 模拟erp提供入库上传接口
/// </summary>
/// <param name="barcodeInfo"></param>
/// <returns></returns>
[HttpPost]
[Route("wms_erp_interface/wms/sale/out")]
public async Task<XRApiResult<XRResultDto>> UploadStockOut([FromBody] dynamic barcodeInfo)
{
return new XRApiResult<XRResultDto>
{
id = Guid.NewGuid().ToString(),
jsonrpc = "",
result = new XRResultDto
{
status = 200,
success = true
}.ToJson()
};
}
/// <summary>
/// 模拟erp提供生产退库上传接口
/// </summary>
/// <param name="barcodeInfo"></param>
/// <returns></returns>
[HttpPost]
[Route("wms_erp_interface/erp/produce/out")]
public async Task<XRResultDto> UploadProducitonOut([FromBody] dynamic barcodeInfo)
{
return new XRResultDto
{
status = 200,
success = true
};
}
/// <summary>
/// 模拟出库
/// </summary>
/// <param name="stockOutParam"></param>
/// <returns></returns>
[HttpPost]
[Route("api/Test/StockOut")]
public async Task<ApiResult<bool>> StockOut([FromBody] StockOutParam stockOutParam)
{
string url = "http://localhost:8078/api/erp/out";
string jsonParam = JsonConvert.SerializeObject(stockOutParam);
string resJson = await HttpRequestHelper.RequestByJson(url, RestSharp.Method.POST, jsonParam);
if (string.IsNullOrEmpty(resJson))
{
return new ApiResult<bool> { ResultCode = "500", Data = false };
}
XRResultDto erpRet = JsonConvert.DeserializeObject<XRResultDto>(resJson);
return new ApiResult<bool> { Data = erpRet.success, ResultCode = erpRet.success ? "200" : "500", ErrorMsg = erpRet.errors };
}
/// <summary>
/// wms上传agv任务
/// </summary>
/// <param name="taskParam"></param>
/// <returns></returns>
[HttpPost]
[Route("ics/taskOrder/addTask")]
public async Task<JSMachine.WMS.RPC.RcsRPC.Dto.RcsApiResult> UploadRcsTask([FromBody] CreateTaskParam taskParam)
{
RcsTaskDto rcsTask = new()
{
TaskId = taskParam.orderId,
StartPositionCode = taskParam.taskOrderDetail.taskPath.Split(',', StringSplitOptions.RemoveEmptyEntries)[0],
EndPositionCode = taskParam.taskOrderDetail.taskPath.Split(',', StringSplitOptions.RemoveEmptyEntries)[1],
Status = 9,
UploadTime=DateTime.Now
};
bool bRet = await _rcsTaskService.Add(rcsTask);
return new JSMachine.WMS.RPC.RcsRPC.Dto.RcsApiResult { code = 1000 };
}
/// <summary>
/// 获取rcs任务列表
/// </summary>
/// <returns></returns>
[HttpPost]
[Route("api/Test/GetRcsTaskLst")]
public async Task<ApiResult<List<RcsTaskDto>>> GetRcsTaskLst()
{
List<RcsTaskDto> rcsTasks = await _rcsTaskService.GetListByExpression(p =>
p.CreationTime > DateTime.Now.Date,
nameof(RcsTaskDto.CreationTime),
SqlSugar.OrderByType.Desc);
return new ApiResult<List<RcsTaskDto>>() { ResultCode = "200", Data = rcsTasks };
}
/// <summary>
/// 修改rcs任务信息
/// </summary>
/// <returns></returns>
[HttpPost]
[Route("api/Test/UpdateRcsTask")]
public async Task<ApiResult<bool>> UpdateRcsTask([FromBody] RcsTaskDto rcsTask)
{
bool bRet = await _rcsTaskService.EditSingal(rcsTask);
return new ApiResult<bool>() { ResultCode = "200", Data = bRet };
}
}
}
@@ -0,0 +1,165 @@
using JSMachine.WMS.App.Dto;
using JSMachine.WMS.App.IService;
using JSMachine.WMS.Common.Dto.Business;
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
using JSMachine.WMS.WebHost.Models;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
namespace JSMachine.WMS.WebHost.Controllers
{
[Route("api/[controller]/[action]")]
public class UserInfoController : ControllerBase
{
private readonly IUserInfoService _userInfoService;
public UserInfoController(IUserInfoService userInfoService)
{
_userInfoService = userInfoService;
}
/// <summary>
/// 获取所有用户信息
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<ApiResult<List<UserInfoDto>>> GetAll()
{
var users = await _userInfoService.GetListByExpression(p => true,
nameof(UserInfoDto.CreationTime),
OrderByType.Desc);
return new ApiResult<List<UserInfoDto>>
{
ResultCode = "200",
Data = users
};
}
/// <summary>
/// 根据ID获取用户信息
/// </summary>
/// <param name="id">用户ID</param>
/// <returns></returns>
[HttpGet("{id}")]
public async Task<ApiResult<UserInfoDto>> GetById(Guid id)
{
var user = await _userInfoService.GetSingalByExpression(p => p.Id == id);
if (user == null)
{
return new ApiResult<UserInfoDto>
{
ResultCode = "404",
ErrorMsg = "用户不存在"
};
}
return new ApiResult<UserInfoDto>
{
ResultCode = "200",
Data = user
};
}
/// <summary>
/// 创建新用户
/// </summary>
/// <param name="userDto">用户信息</param>
/// <returns></returns>
[HttpPost]
public async Task<ApiResult<bool>> Create([FromBody] UserInfoDto userDto)
{
if (userDto == null)
{
return new ApiResult<bool>
{
ResultCode = "400",
ErrorMsg = "请求参数不能为空"
};
}
var result = await _userInfoService.Add(userDto);
return new ApiResult<bool>
{
ResultCode = "200",
Data = result
};
}
/// <summary>
/// 更新用户信息
/// </summary>
/// <param name="id">用户ID</param>
/// <param name="userDto">更新后的用户信息</param>
/// <returns></returns>
[HttpPut("{id}")]
public async Task<ApiResult<bool>> Update(Guid id, [FromBody] UserInfoDto userDto)
{
if (userDto == null)
{
return new ApiResult<bool>
{
ResultCode = "400",
ErrorMsg = "请求参数不能为空"
};
}
var existingUser = await _userInfoService.GetSingalByExpression(p => p.Id == id);
if (existingUser == null)
{
return new ApiResult<bool>
{
ResultCode = "404",
ErrorMsg = "用户不存在"
};
}
// 更新用户信息
var result = await _userInfoService.EditSingal(userDto);
return new ApiResult<bool>
{
ResultCode = "200",
Data = result
};
}
/// <summary>
/// 删除用户
/// </summary>
/// <param name="id">用户ID</param>
/// <returns></returns>
[HttpDelete("{id}")]
public async Task<ApiResult<bool>> Delete(Guid id)
{
var existingUser = await _userInfoService.GetSingalByExpression(p => p.Id == id);
if (existingUser == null)
{
return new ApiResult<bool>
{
ResultCode = "404",
ErrorMsg = "用户不存在"
};
}
var result = await _userInfoService.DeleteById(id);
return new ApiResult<bool>
{
ResultCode = "200",
Data = result
};
}
[HttpPost]
public async Task<ApiResult<UserPermission>> Login([FromBody] UserInfoDto userInfo)
{
if (userInfo == null || string.IsNullOrEmpty(userInfo.UserId) || string.IsNullOrEmpty(userInfo.Password))
return new ApiResult<UserPermission> { ResultCode = "500", ErrorMsg = "参数不合法" };
UserInfoDto validUser = await _userInfoService.GetSingalByExpression(p=>p.UserId== userInfo.UserId&&p.Password== userInfo.Password);
if (validUser == null)
return new ApiResult<UserPermission> { ResultCode = "500", ErrorMsg = "用户名或密码错误" };
return new ApiResult<UserPermission> { ResultCode="200",Data=new UserPermission {Token=Guid.NewGuid().ToString("N"),UserInfo= validUser } };
}
}
}
@@ -0,0 +1,421 @@
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
}
}
@@ -0,0 +1,192 @@
using JSMachine.WMS.Business.RcsCallBack.IService;
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
using JSMachine.WMS.RPC.RcsRPC.Dto.In;
using Microsoft.AspNetCore.Mvc;
using JSMachine.WMS.RPC.RcsRPC.Dto;
using JSMachine.WMS.Business.StockIn.IService;
using JSMachine.WMS.RPC.ErpRPC.Dto.In.XRBusinessResult;
using JSMachine.WMS.RPC.ErpRPC.Dto.Out.XRBusinessResult;
using JSMachine.WMS.Business.StockOut.IService;
using JSMachine.WMS.Infrastructure.Helper;
using Newtonsoft.Json;
using JSMachine.WMS.App.Dto.Enum;
using JSMachine.WMS.RPC.ErpRPC.Dto.In;
using Microsoft.IdentityModel.Tokens;
using JSMachine.WMS.App.IService;
using JSMachine.WMS.App.Dto;
using JSMachine.WMS.Common.Cache;
using JSMachine.WMS.Application.IService;
using JSMachine.WMS.Application.Dto;
using JSMachine.WMS.Domain.Entity.Enums;
namespace JSMachine.WMS.WebHost.Controllers
{
/// <summary>
/// WMS 核心业务接口,接收 RCS、PDA 和 ERP 请求并委托给对应业务服务。
/// </summary>
public class WmsController : ControllerBase
{
private IStockInService _stockInService;
private IOperationLogService _operationLogService;
private IStockOutService _stockOutService;
/// <summary>创建 WMS 核心业务控制器。</summary>
/// <param name="stockInService">入库业务服务。</param>
/// <param name="stockOutService">出库业务服务。</param>
/// <param name="operationLogService">操作日志服务。</param>
public WmsController(
IStockInService stockInService,
IStockOutService stockOutService,
IOperationLogService operationLogService)
{
_stockInService = stockInService;
_stockOutService = stockOutService;
_operationLogService = operationLogService;
}
#region 通过提供接口,给Rcs调用,获取AGV上报的任务状态
/// <summary>
/// Rcs上传agv作业执行状态
/// </summary>
/// <param name="callBackWmsParam"></param>
/// <returns></returns>
[Route("api/Wms/PostAgvExcutionStatus")]
[HttpPost]
public async Task<RcsApiResult> PostAgvExcutionStatus([FromBody] AgvExcutionInfo agvExcutionInfo)
{
LogHelper.Info($"收到Rcs上报的小车执行状态信息,任务Id {agvExcutionInfo.OrderId},当前状态 {agvExcutionInfo.Status}");
_ = _operationLogService.Add(new OperationLogDto
{
OperationSource = OperationSource.RCS,
OperationType = OperationType.RcsCallBack,
NewObject = JsonConvert.SerializeObject(agvExcutionInfo)
});
if (agvExcutionInfo == null || string.IsNullOrEmpty(agvExcutionInfo.OrderId))
{
return await Task.FromResult(new RcsApiResult { code = 500, data = "参数不合法" });
}
RcsCallbackCache.RcsCallbackQueue.Enqueue(agvExcutionInfo);
return await Task.FromResult(new RcsApiResult()
{
code = 1000,
});
}
#endregion
#region PDA入库
/// <summary>接收 PDA 入库请求并创建入库业务任务。</summary>
/// <param name="pdaInParam">PDA 提交的入库参数。</param>
/// <returns>标准化入库处理结果。</returns>
[Route("api/wms/StockInByPda")]
[HttpPost]
public async Task<ApiResult<bool>> StockInByPda([FromBody] PDAInParam pdaInParam)
{
_ = _operationLogService.Add(new OperationLogDto
{
OperationSource = OperationSource.PDA,
OperationType = OperationType.StockIn,
NewObject = JsonConvert.SerializeObject(pdaInParam)
});
ApiResult<bool> apiResult = new();
string msg = await _stockInService.StockIn(pdaInParam);
if (string.IsNullOrEmpty(msg))
{
apiResult.ResultCode = "200";
apiResult.Data = true;
}
else
{
apiResult.ResultCode = "500";
apiResult.Data = false;
apiResult.ErrorMsg = msg;
}
return apiResult;
}
#endregion
#region 销售出库/生产退库
private static readonly SemaphoreSlim _requestSemaphore = new(1, 1);
/// <summary>
/// 销售出库/生产退库
/// </summary>
/// <param name="erpSaleOutParam"></param>
/// <returns></returns>
[Route("api/erp/out")]
[HttpPost]
public async Task<XRResultDto> Out([FromBody] StockOutParam erpSaleOutParam)
{
await _requestSemaphore.WaitAsync();
try
{
LogHelper.Info($"收到erp出库请求,请求方IP {HttpContext.Connection.RemoteIpAddress}," +
$"原始参数信息 {JsonConvert.SerializeObject(erpSaleOutParam)}");
_ = _operationLogService.Add(new OperationLogDto
{
OperationSource = OperationSource.ERP,
OperationType = erpSaleOutParam.transport==4 ? OperationType.ProductionOut : OperationType.SaleOut,
NewObject = JsonConvert.SerializeObject(erpSaleOutParam)
});
XRResultDto apiResult = new();
string errMsg = await _stockOutService.Stockout(erpSaleOutParam);
if (string.IsNullOrEmpty(errMsg))
{
apiResult.success = true;
apiResult.status = 200;
}
else
{
apiResult.success = false;
apiResult.status = 500;
apiResult.errors = errMsg;
}
return apiResult;
}
catch (Exception ex)
{
LogHelper.Error(ex);
return new XRResultDto { status = 500, success = false, errors = "WMS服务端发生未知错误" };
}
finally
{
_requestSemaphore.Release();
}
}
#endregion
#region 出库撤单
/// <summary>
/// 出库撤单
/// </summary>
/// <param name="cancelOrderParam"></param>
/// <returns></returns>
[Route("api/erp/retreat")]
[HttpPost]
public async Task<XRNewResultDto<int>> ErpCancelOrder([FromBody] ErpCancelOrderParam cancelOrderParam)
{
LogHelper.Info($"收到erp出库撤单请求,请求方IP {HttpContext.Connection.RemoteIpAddress}," +
$"原始参数信息 {JsonConvert.SerializeObject(cancelOrderParam)}");
_ = _operationLogService.Add(new OperationLogDto
{
OperationSource = OperationSource.ERP,
OperationType = OperationType.StockOutCancel,
NewObject = JsonConvert.SerializeObject(cancelOrderParam)
});
return await _stockOutService.ErpCancelOrder(cancelOrderParam);
}
#endregion
}
}