wanshenmean
4 天以前 90fa55064597236b9581304f232a607ffc7b730e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
using Autofac;
using Newtonsoft.Json;
using System.Diagnostics.CodeAnalysis;
using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEA_Core;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_Core.Enums;
using WIDESEAWCS_DTO;
using WIDESEAWCS_DTO.Stock;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_ITaskInfoRepository;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob.DTO;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
 
namespace WIDESEAWCS_TaskInfoService.Flows
{
    /// <summary>
    /// 出库任务流程服务。
    /// 负责出库任务接收初始化、状态推进及堆垛机完成处理。
    /// </summary>
    public class OutboundTaskFlowService : IOutboundTaskFlowService
    {
        private readonly IRouterService _routerService;
        private readonly HttpClientHelper _httpClientHelper;
        private readonly IRobotTaskService _robotTaskService;
        private readonly ITaskRepository _taskRepository;
        private readonly IComponentContext _componentContext;
 
        /// <summary>
        /// 初始化出库任务流程服务。
        /// </summary>
        /// <param name="routerService">路由服务。</param>
        /// <param name="httpClientHelper">WMS接口调用帮助类。</param>
        /// <param name="robotTaskService">机械手任务服务。</param>
        /// <param name="taskRepository">任务仓储(用于删除出库任务)。</param>
        /// <param name="componentContext">Autofac组件上下文(用于延迟解析ITaskService以避免循环依赖)。</param>
        public OutboundTaskFlowService(IRouterService routerService, HttpClientHelper httpClientHelper, IRobotTaskService robotTaskService, ITaskRepository taskRepository, IComponentContext componentContext)
        {
            _routerService = routerService;
            _httpClientHelper = httpClientHelper;
            _robotTaskService = robotTaskService;
            _taskRepository = taskRepository;
            _componentContext = componentContext;
        }
 
        /// <summary>
        /// 延迟解析ITaskService以避免循环依赖
        /// </summary>
        private ITaskService TaskService => _componentContext.Resolve<ITaskService>();
 
        /// <summary>
        /// 接收WMS任务时初始化出库任务。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        public void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
        {
            int taskType = task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty ? 100 : task.TaskType;
            Dt_Router router = _routerService.QueryNextRoute(source.Roadway, source.TargetAddress, taskType);
            if (router == null)
            {
                return;
            }
 
            task.TaskStatus = (int)TaskOutStatusEnum.OutNew;
            task.CurrentAddress = source.SourceAddress;
            task.NextAddress = router.ChildPosi;
        }
 
        /// <summary>
        /// 推进出库任务状态,并在关键状态调用WMS接口。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>推进结果。</returns>
        public WebResponseContent MoveToNextStatus([NotNull] Dt_Task task)
        {
            if (task.TaskStatus >= (int)TaskOutStatusEnum.OutFinish)
                return WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskStatus}】");
 
            task.TaskStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskOutStatusEnum>();
            if (task.TaskStatus <= 0)
                return WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskStatus}】");
 
            if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.Outbound)
            {
                return GetWMSOutboundTrayTask(task);
            }
 
            if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty)
            {
                WebResponseContent content = _robotTaskService.GetWMSRobotTask(task);
                if (!content.Status)
                {
                    return content;
                }
                return OutboundFinishTaskTray(task);
            }
 
            if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutExecuting)
            {
                return WebResponseContent.Instance.OK();
            }
 
            return UpdateWMSTaskStatus(task);
        }
 
        /// <summary>
        /// 处理堆垛机出库完成动作。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>处理结果。</returns>
        public WebResponseContent CompleteStackerTask([NotNull] Dt_Task task)
        {
            WebResponseContent content = new WebResponseContent();
            if (task.TaskStatus != (int)TaskOutStatusEnum.SC_OutExecuting)
            {
                return WebResponseContent.Instance.OK();
            }
 
            int taskType = task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty ? 100 : task.TaskType;
            Dt_Router router = _routerService.QueryNextRoute(task.NextAddress, task.TargetAddress, taskType);
            if (router == null)
            {
                return WebResponseContent.Instance.Error("未找到设备路由信息");
            }
 
            int nextStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskOutStatusEnum>();
            task.TaskStatus = nextStatus;
            task.CurrentAddress = task.NextAddress;
            task.NextAddress = router.ChildPosi;
            task.ModifyDate = DateTime.Now;
            task.Modifier = "System";
 
            // 通知WMS出库完成并获取返回结果
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.OutboundFinishTaskAsync),
                new StockInfoDTO { PalletCode = task.PalletCode, TaskNum = task.TaskNum }.ToJson());
 
            if (!result.IsSuccess || !result.Data.Status)
            {
                return content.Error($"通知WMS系统堆垛机出库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
            }
 
            // 处理WMS返回的入库任务(如果有)
            if (result.Data?.Data != null)
            {
                var inboundTaskJson = result.Data.Data.ToString();
                var inboundTaskDto = JsonConvert.DeserializeObject<WMSTaskDTO>(inboundTaskJson);
 
                if (inboundTaskDto != null)
                {
                    // 先删除本地出库任务,避免托盘号唯一键冲突
                    _taskRepository.DeleteAndMoveIntoHty(task, OperateTypeEnum.自动完成);
 
                    // 调用ReceiveWMSTask创建本地入库任务
                    var receiveResult = TaskService.ReceiveWMSTask(new List<WMSTaskDTO> { inboundTaskDto });
                    if (!receiveResult.Status)
                    {
                        return content.Error($"创建本地入库任务失败: {receiveResult.Message}");
                    }
                }
            }
 
            return content.OK($"通知WMS系统堆垛机出库完成成功,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】");
        }
 
        /// <summary>
        /// 通知WMS出库完成。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>通知结果。</returns>
        private WebResponseContent NotifyWMSOutboundFinish(Dt_Task task)
        {
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.OutboundFinishTaskAsync),
                new StockInfoDTO { PalletCode = task.PalletCode, TaskNum = task.TaskNum }.ToJson());
 
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"通知WMS系统堆垛机出库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
 
            return WebResponseContent.Instance.OK();
        }
 
        /// <summary>
        /// 从WMS获取空托盘出库任务。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>调用结果,成功时Data中包含一个WMSTaskDTO集合。</returns>
        private WebResponseContent GetWMSOutboundTrayTask(Dt_Task task)
        {
            int warehouseId = _robotTaskService.MapWarehouseIdConfigKey(task.TargetAddress);
            string sourceLineNo = _robotTaskService.ResolveRobotRuleValue(task.TargetAddress, "AddressSourceLineNoMap", task.TargetAddress);
 
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.GetOutBoundTrayTaskAsync),
                new CreateTaskDto { WarehouseId = warehouseId, TargetAddress = sourceLineNo }.ToJson());
 
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"获取WMS系统空托盘出库任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
 
            WMSTaskDTO? wMSTask = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.Data?.ToString() ?? string.Empty);
            if (wMSTask == null)
                return WebResponseContent.Instance.Error($"获取WMS系统空托盘出库任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【WMS未返回有效任务数据】");
 
            return WebResponseContent.Instance.OK("成功", new List<WMSTaskDTO> { wMSTask });
        }
 
        /// <summary>
        /// 将任务状态同步到WMS。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>同步结果。</returns>
        private WebResponseContent UpdateWMSTaskStatus(Dt_Task task)
        {
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.UpdateTaskByStatus),
                new UpdateTaskDto { Id = task.TaskNum, NewStatus = task.TaskStatus }.ToJson());
 
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"调用WMS接口更新任务状态失败,任务号:【{task.TaskNum}】,错误信息:【{result.Data?.Message}】");
 
            return WebResponseContent.Instance.OK();
        }
 
        /// <summary>
        /// 空托盘出库完成同步到WMS。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>同步结果。</returns>
        private WebResponseContent OutboundFinishTaskTray(Dt_Task task)
        {
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.OutboundFinishTaskTray),
                new CreateTaskDto { PalletCode = task.PalletCode, SourceAddress = task.SourceAddress }.ToJson());
 
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"调用WMS接口更新任务状态失败,任务号:【{task.TaskNum}】,错误信息:【{result.Data?.Message}】");
 
            return WebResponseContent.Instance.OK();
        }
    }
}