using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Mvc;
|
using WIDESEA_Core;
|
using WIDESEA_Core.BaseController;
|
using WIDESEA_DTO.MES;
|
using WIDESEA_IStockService;
|
using WIDESEA_IBasicService;
|
using WIDESEA_ISystemService;
|
using WIDESEA_Model.Models;
|
using WIDESEA_Common.Constants;
|
using WIDESEA_Common.StockEnum;
|
|
namespace WIDESEA_WMSServer.Controllers.Stock
|
{
|
/// <summary>
|
/// 库存明细
|
/// </summary>
|
[Route("api/StockInfoDetail")]
|
[ApiController]
|
public class StockInfoDetailController : ApiBaseController<IStockInfoDetailService, Dt_StockInfoDetail>
|
{
|
private readonly IMesService _mesService;
|
private readonly ISys_DictionaryService _sysDictionaryService;
|
private readonly IStockInfoService _stockInfoService;
|
private readonly IMESDeviceConfigService _mesDeviceConfigService;
|
private readonly IMesUploadHelper _mesUploadHelper;
|
|
public StockInfoDetailController(
|
IStockInfoDetailService service,
|
IMesService mesService,
|
ISys_DictionaryService sysDictionaryService,
|
IStockInfoService stockInfoService,
|
IMESDeviceConfigService mesDeviceConfigService,
|
IMesUploadHelper mesUploadHelper) : base(service)
|
{
|
_mesService = mesService;
|
_sysDictionaryService = sysDictionaryService;
|
_stockInfoService = stockInfoService;
|
_mesDeviceConfigService = mesDeviceConfigService;
|
_mesUploadHelper = mesUploadHelper;
|
}
|
|
/// <summary>
|
/// 托盘电芯绑定 - 调用MES接口
|
/// </summary>
|
/// <param name="dto">绑定请求参数</param>
|
/// <returns>操作结果</returns>
|
[HttpPost("bindContainer")]
|
public async Task<WebResponseContent> BindContainer([FromBody] BindContainerRequestDto dto)
|
{
|
var response = new WebResponseContent();
|
|
try
|
{
|
// 1. 参数验证
|
if (dto.SfcList == null || !dto.SfcList.Any())
|
{
|
return response.Error("电芯码列表不能为空");
|
}
|
|
// 2. 验证电芯状态(非'已锁定'状态允许绑定)
|
var stockDetail = await Service.Repository.QueryFirstAsync(x => dto.SfcList.Contains(x.SerialNumber));
|
if (stockDetail != null && stockDetail.Status == 99)
|
{
|
return response.Error("当前库存明细包含已锁定状态,不允许执行绑定操作");
|
}
|
var stockInfo = await _stockInfoService.Repository.QueryFirstAsync(x => stockDetail.StockId == x.Id);
|
|
// 3. 动态获取MES凭证
|
var mesConfig = _mesDeviceConfigService.GetByDeviceName("组盘机械手");
|
string equipmentCode = mesConfig?.EquipmentCode ?? StockConstants.MES_EQUIPMENT_CODE;
|
string resourceCode = mesConfig?.ResourceCode ?? StockConstants.MES_RESOURCE_CODE;
|
string token = mesConfig?.Token;
|
|
// 4. 构造MES请求 - 将电芯列表转换为ContainerSfcItem格式
|
var mesRequest = new BindContainerRequest
|
{
|
EquipmentCode = equipmentCode,
|
ResourceCode = resourceCode,
|
LocalTime = DateTime.Now,
|
ContainerCode = stockInfo.PalletCode,
|
ContainerSfcList = dto.SfcList.Select(sfc => new ContainerSfcItem
|
{
|
Sfc = sfc,
|
Location = dto.Location ?? ""
|
}).ToList(),
|
OperationType = dto.OperationType
|
};
|
|
string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest);
|
|
// 5. 异步调用MES接口(fire-and-forget)
|
_mesUploadHelper.FireAndForget(
|
stockInfo.PalletCode,
|
MesUploadStatusEnum.组盘上传成功,
|
"BindContainer",
|
requestJson,
|
() =>
|
{
|
var result = string.IsNullOrWhiteSpace(token)
|
? _mesService.BindContainer(mesRequest)
|
: _mesService.BindContainer(mesRequest, token);
|
return (
|
result?.IsSuccess ?? false,
|
System.Text.Json.JsonSerializer.Serialize(result),
|
result?.ErrorMessage ?? "未知错误"
|
);
|
},
|
App.User.UserName);
|
|
// 6. 立即返回成功响应
|
return response.OK("托盘电芯绑定成功");
|
}
|
catch (Exception ex)
|
{
|
return response.Error($"托盘电芯绑定失败: {ex.Message}");
|
}
|
}
|
|
/// <summary>
|
/// 托盘电芯解绑 - 调用MES接口
|
/// </summary>
|
/// <param name="dto">解绑请求参数</param>
|
/// <returns>操作结果</returns>
|
[HttpPost("unbindContainer")]
|
public async Task<WebResponseContent> UnbindContainer([FromBody] UnbindContainerRequestDto dto)
|
{
|
var response = new WebResponseContent();
|
|
try
|
{
|
// 1. 参数验证
|
if (dto.SfcList == null || !dto.SfcList.Any())
|
{
|
return response.Error("电芯码列表不能为空");
|
}
|
|
// 2. 验证电芯状态(非'已锁定'状态允许解绑)
|
var stockDetail = await Service.Repository.QueryFirstAsync(x => dto.SfcList.Contains(x.SerialNumber));
|
if (stockDetail != null && stockDetail.Status == 99)
|
{
|
return response.Error("当前库存明细包含已锁定状态,不允许执行解绑操作");
|
}
|
var stockInfo = await _stockInfoService.Repository.QueryFirstAsync(x => stockDetail.StockId == x.Id);
|
|
// 3. 动态获取MES凭证
|
var mesConfig = _mesDeviceConfigService.GetByDeviceName("组盘机械手");
|
string equipmentCode = mesConfig?.EquipmentCode ?? StockConstants.MES_EQUIPMENT_CODE;
|
string resourceCode = mesConfig?.ResourceCode ?? StockConstants.MES_RESOURCE_CODE;
|
string token = mesConfig?.Token;
|
|
// 4. 构造MES请求
|
var mesRequest = new UnBindContainerRequest
|
{
|
EquipmentCode = equipmentCode,
|
ResourceCode = resourceCode,
|
LocalTime = DateTime.Now,
|
ContainCode = stockInfo.PalletCode,
|
SfcList = dto.SfcList
|
};
|
|
string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest);
|
|
// 5. 异步调用MES接口(fire-and-forget)
|
_mesUploadHelper.FireAndForget(
|
stockInfo.PalletCode,
|
MesUploadStatusEnum.拆盘上传成功,
|
"UnbindContainer",
|
requestJson,
|
() =>
|
{
|
var result = string.IsNullOrWhiteSpace(token)
|
? _mesService.UnBindContainer(mesRequest)
|
: _mesService.UnBindContainer(mesRequest, token);
|
return (
|
result?.IsSuccess ?? false,
|
System.Text.Json.JsonSerializer.Serialize(result),
|
result?.ErrorMessage ?? "未知错误"
|
);
|
},
|
App.User.UserName);
|
|
// 6. 立即返回成功响应
|
return response.OK("托盘电芯解绑成功");
|
}
|
catch (Exception ex)
|
{
|
return response.Error($"托盘电芯解绑失败: {ex.Message}");
|
}
|
}
|
|
/// <summary>
|
/// 托盘NG电芯上报 - 调用MES接口
|
/// </summary>
|
/// <param name="dto">NG上报请求参数</param>
|
/// <returns>操作结果</returns>
|
[HttpPost("containerNgReport")]
|
public async Task<WebResponseContent> ContainerNgReport([FromBody] ContainerNgReportRequestDto dto)
|
{
|
var response = new WebResponseContent();
|
|
try
|
{
|
// 1. 参数验证
|
if (string.IsNullOrWhiteSpace(dto.PalletCode))
|
{
|
return response.Error("托盘编号不能为空");
|
}
|
|
if (dto.NgSfcList == null || !dto.NgSfcList.Any())
|
{
|
return response.Error("NG电芯列表不能为空");
|
}
|
|
// 2. 验证电芯状态(非'已锁定'状态允许NG上报)
|
var sfcList = dto.NgSfcList.Select(x => x.Sfc).ToList();
|
var stockDetail = await Service.Repository.QueryFirstAsync(x => sfcList.Contains(x.SerialNumber));
|
if (stockDetail != null && stockDetail.Status == 99)
|
{
|
return response.Error("当前库存明细包含已锁定状态,不允许执行NG上报操作");
|
}
|
var stockInfo = await _stockInfoService.Repository.QueryFirstAsync(x => stockDetail.StockId == x.Id);
|
|
// 3. 动态获取MES凭证
|
var mesConfig = _mesDeviceConfigService.GetByDeviceName("组盘机械手");
|
string equipmentCode = mesConfig?.EquipmentCode ?? StockConstants.MES_EQUIPMENT_CODE;
|
string resourceCode = mesConfig?.ResourceCode ?? StockConstants.MES_RESOURCE_CODE;
|
|
// 4. 构造MES请求 - 将DTO格式转换为MES请求格式
|
var mesRequest = new ContainerNgReportRequest
|
{
|
EquipmentCode = equipmentCode,
|
ResourceCode = resourceCode,
|
LocalTime = DateTime.Now,
|
ContainerCode = stockInfo.PalletCode,
|
NgSfcList = dto.NgSfcList.Select(ng => new NgSfcItem
|
{
|
Sfc = ng.Sfc,
|
NgCode = ng.NgCode,
|
NgEquipmentCode = ng.NgEquipmentCode,
|
NgResourceCode = ng.NgResourceCode
|
}).ToList()
|
};
|
|
string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest);
|
|
// 5. 异步调用MES接口(fire-and-forget)
|
_mesUploadHelper.FireAndForget(
|
stockInfo.PalletCode,
|
MesUploadStatusEnum.NG上报成功,
|
"ContainerNgReport",
|
requestJson,
|
() =>
|
{
|
var result = _mesService.ContainerNgReport(mesRequest);
|
return (
|
result?.IsSuccess ?? false,
|
System.Text.Json.JsonSerializer.Serialize(result),
|
result?.ErrorMessage ?? "未知错误"
|
);
|
},
|
App.User.UserName);
|
|
// 6. 立即返回成功响应
|
return response.OK("NG电芯上报成功");
|
}
|
catch (Exception ex)
|
{
|
return response.Error($"NG电芯上报失败: {ex.Message}");
|
}
|
}
|
|
/// <summary>
|
/// 从配置字典中获取配置值
|
/// </summary>
|
/// <param name="configs">配置字典列表</param>
|
/// <param name="key">配置键</param>
|
/// <param name="defaultValue">默认值</param>
|
/// <returns>配置值</returns>
|
private string GetConfigValue(System.Collections.Generic.List<WIDESEA_DTO.System.VueDictionaryDTO> configs, string key, string defaultValue = "")
|
{
|
if (configs != null)
|
{
|
var config = configs.FirstOrDefault(c => c.DicNo == key);
|
if (config != null && config.Data != null)
|
{
|
// Data是dynamic类型,尝试获取第一个元素的value属性
|
try
|
{
|
// 使用dynamic来访问匿名类型的属性
|
dynamic data = config.Data;
|
if (data != null)
|
{
|
// data可能是IEnumerable或者单个对象
|
var enumerable = data as System.Collections.IEnumerable;
|
if (enumerable != null)
|
{
|
foreach (var item in enumerable)
|
{
|
// 获取第一个元素
|
dynamic firstItem = item;
|
var value = firstItem.value;
|
return value?.ToString() ?? defaultValue;
|
}
|
}
|
}
|
}
|
catch
|
{
|
// 如果无法获取,返回默认值
|
return defaultValue;
|
}
|
}
|
}
|
return defaultValue;
|
}
|
}
|
}
|