路径算法调整为动态规划方式,新增预任务申请功能

This commit is contained in:
DEVICE8\12494
2023-06-13 18:11:37 +08:00
parent 759b66d789
commit 5a49b9ba97
14 changed files with 602 additions and 69 deletions

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Org.BouncyCastle.Asn1.Mozilla;
namespace Tnb.WarehouseMgr.Entities.Consts
{
@@ -12,5 +13,21 @@ namespace Tnb.WarehouseMgr.Entities.Consts
/// 出入库单据状态TypeID
/// </summary>
public const string WMS_INSTOCK_D_BILL_STATUS_TYPEID = "25065133038101";
/// <summary>
/// 预任务生成EnCode
/// </summary>
public const string WMS_PRETASK_H_ENCODE = "PreTaskGen";
/// <summary>
/// 预任务单据状态-待下发Id
/// </summary>
public const string PRETASK_BILL_STATUS_DXF_ID = "26126822610469";
/// <summary>
/// 预任务生成业务类型-载具移入Id
/// </summary>
public const string BIZTYPE_MOVEIN_ID = "26121988909861";
/// <summary>
/// 单据状态-作业中
/// </summary>
public const string BILLSTATUS_ON_ID = "25065143245845";
}
}

View File

@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tnb.WarehouseMgr.Entities.Dto
{
/// <summary>
/// 生成预任务成功后输入参数
/// </summary>
public class GenPreTaskUpInput
{
/// <summary>
/// 预任务Id
/// </summary>
public string PreTaskId { get; set; }
/// <summary>
/// 载具Id
/// </summary>
public string CarryId { get; set; }
/// <summary>
/// 载具起始库位Id
/// </summary>
public string CarryStartLocationId { get; set; }
/// <summary>
/// 载具起始库位编号
/// </summary>
public string CarryStartLocationCode { get; set; }
/// <summary>
/// 库位IdS
/// </summary>
public List<string> LocationIds { get; set; }
/// <summary>
/// 预任务操作记录
/// </summary>
public List<WmsHandleH> PreTaskRecords { get; set; }
/// <summary>
/// 预任务条码记录
/// </summary>
public List<WmsHandleCode> PreTaskHandleCodes { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tnb.WarehouseMgr.Entities
{
public interface IWmsRoadEntity
{
string startpoint_id { get; set; }
string endpoint_id { get; set; }
}
}

View File

@@ -134,4 +134,24 @@ public partial class WmsPretaskH : BaseEntity<string>
/// </summary>
public DateTime? timestamp { get; set; }
/// <summary>
/// 流程任务Id
/// </summary>
public string? f_flowtaskid { get; set; }
/// <summary>
/// 流程引擎Id
/// </summary>
public string? f_flowid { get; set; }
/// <summary>
/// 起始库位编号
/// </summary>
public string startlocation_code { get; set; } = string.Empty;
/// <summary>
/// 目标库位编号
/// </summary>
public string endlocation_code { get; set; } = string.Empty;
}

View File

@@ -8,7 +8,7 @@ namespace Tnb.WarehouseMgr.Entities;
/// 路段管理表
/// </summary>
[SugarTable("wms_road")]
public partial class WmsRoad : BaseEntity<string>
public partial class WmsRoad : BaseEntity<string>, IWmsRoadEntity
{
public WmsRoad()
{

View File

@@ -34,5 +34,11 @@ namespace Tnb.WarehouseMgr.Interfaces
/// <param name="preTasks"></param>
/// <returns></returns>
Task<bool> GenPreTask(List<WmsPretaskH> preTasks);
/// <summary>
/// 生成预任务成功后操作
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task GenTaskHandleAfter(GenPreTaskUpInput input);
}
}

View File

@@ -16,5 +16,7 @@ namespace Tnb.WarehouseMgr
public class BaseWareHouseService : IOverideVisualDevService, IDynamicApiController, ITransient
{
public OverideVisualDevFunc OverideFuncs { get; } = new OverideVisualDevFunc();
}
}

View File

@@ -0,0 +1,215 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
//using JNPF.Common.Contracts;
//using NPOI.SS.Formula.Functions;
//using Tnb.WarehouseMgr.Entities;
//namespace Tnb.WarehouseMgr
//{
// /// <summary>
// /// 迪杰斯特拉(最短路径算法)
// /// </summary>
// public class Dijkstra<T> where T : BaseEntity<string>, IWmsRoadEntity, new()
// {
// public static int MAX = int.MaxValue;
// public int mEdgNum; // 边的数量
// public VNode[] mVexs; // 顶点数组
// //private EData[] edges; //边的数组
// /*
// * 创建图
// *
// * 参数说明:
// * vexs -- 顶点数组
// * edges -- 边
// */
// public Dijkstra(string[] vexs, EData[] edges)
// {
// // 初始化"顶点数"和"边数"
// int vlen = vexs.Length;
// int elen = edges.Length;
// // 初始化"顶点"
// mVexs = new VNode[vlen];
// for (int i = 0; i < mVexs.Length; i++)
// {
// mVexs[i] = new VNode();
// mVexs[i].data = vexs[i];
// mVexs[i].firstEdge = null;
// }
// // 初始化"边"
// mEdgNum = elen;
// for (int i = 0; i < elen; i++)
// {
// // 读取边的起始顶点和结束顶点
// string c1 = edges[i].start;
// string c2 = edges[i].end;
// int weight = edges[i].weight;
// // 读取边的起始顶点和结束顶点
// int p1 = GetPosition(c1);
// int p2 = GetPosition(c2);
// // 初始化node1
// ENode node1 = new ENode();
// node1.ivex = p2;
// node1.weight = weight;
// // 将node1链接到"p1所在链表的末尾"
// if (mVexs[p1].firstEdge == null)
// mVexs[p1].firstEdge = node1;
// else
// LinkLast(mVexs[p1].firstEdge, node1);
// // 初始化node2
// ENode node2 = new ENode();
// node2.ivex = p1;
// node2.weight = weight;
// // 将node2链接到"p2所在链表的末尾"
// if (mVexs[p2].firstEdge == null)
// mVexs[p2].firstEdge = node2;
// else
// LinkLast(mVexs[p2].firstEdge, node2);
// }
// }
// /*
// * 将node节点链接到list的最后
// */
// private void LinkLast(ENode list, ENode node)
// {
// ENode p = list;
// while (p.nextEdge != null)
// p = p.nextEdge;
// p.nextEdge = node;
// }
// /*
// * 返回ch位置
// */
// private int GetPosition(string ch)
// {
// for (int i = 0; i < mVexs.Length; i++)
// if (mVexs[i].data == ch)
// return i;
// return -1;
// }
// /*
// * 获取边<start, end>的权值若start和end不是连通的则返回无穷大。
// */
// private int GetWeight(int start, int end)
// {
// if (start == end)
// return 0;
// ENode node = mVexs[start].firstEdge;
// while (node != null)
// {
// if (end == node.ivex)
// return node.weight;
// node = node.nextEdge;
// }
// return MAX;
// }
// /*
// * Dijkstra最短路径。
// * 即,统计图中"起点D"到其它各个顶点的最短路径。
// *
// * 参数说明:
// * vs -- 起始顶点(start vertex)。
// * prev -- 前驱顶点数组。即prev[i]的值是"起点D"到"顶点i"的最短路径所经历的全部顶点中,位于"顶点i"之前的那个顶点。
// * dist -- 长度数组。即dist[i]是"起点D"到"顶点i"的最短路径的长度。
// */
// public void CalcDijkstra(int vs, int[] prev, int[] dist, List<T> roads)
// {
// //List<T> vertexs = new(); //最短路径串联的点位列表
// // flag[i]=true表示"起点D"到"顶点i"的最短路径已成功获取。
// bool[] flag = new bool[mVexs.Length];
// // 初始化
// for (int i = 0; i < mVexs.Length; i++)
// {
// flag[i] = false; // 顶点i的最短路径还没获取到。
// prev[i] = 0; // 顶点i的前驱顶点为0。
// dist[i] = GetWeight(vs, i); // 顶点i的最短路径为"起点D"到"顶点i"的权。
// }
// // 对"起点D"自身进行初始化
// flag[vs] = true;
// dist[vs] = 0;
// // 遍历mVexs.Length-1次每次找出一个顶点的最短路径。
// int k = 0;
// for (int i = 1; i < mVexs.Length; i++)
// {
// // 寻找当前最小的路径
// // 即在未获取最短路径的顶点中找到离起点D最近的顶点(k)。
// int min = MAX;
// for (int j = 0; j < mVexs.Length; j++)
// {
// if (flag[j] == false && dist[j] < min)
// {
// min = dist[j];
// k = j;
// }
// }
// // 标记"顶点k"为已经获取到最短路径
// flag[k] = true;
// // 更新当前最短路径和前驱顶点
// // 即,更新"未获取最短路径的顶点的最短路径和前驱顶点"。
// for (int j = 0; j < mVexs.Length; j++)
// {
// int tmp = GetWeight(k, j);
// tmp = (tmp == MAX ? MAX : (min + tmp)); // 防止溢出
// if (flag[j] == false && (tmp < dist[j]))
// {
// dist[j] = tmp;
// prev[j] = k;
// }
// }
// }
// }
// }
// /// <summary>
// /// 邻接表中表对应的链表的顶点
// /// </summary>
// public class ENode
// {
// public int ivex; // 该边所指向的顶点的位置
// public int weight; // 该边的权
// public ENode nextEdge; // 指向下一条弧的指针
// }
// /// <summary>
// /// 邻接表中表的顶点
// /// </summary>
// public class VNode
// {
// public string data; // 顶点信息
// public ENode firstEdge; // 指向第一条依附该顶点的弧
// }
// /// <summary>
// /// 边的结构体
// /// </summary>
// public class EData
// {
// public string start; // 边的起点
// public string end; // 边的终点
// public int weight; // 边的权重
// public EData(string start, string end, int weight)
// {
// this.start = start;
// this.end = end;
// this.weight = weight;
// }
// }
//}

View File

@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JNPF.Templates;
using Microsoft.AspNetCore.Mvc;
using NPOI.SS.Formula.Functions;
using Spire.Doc;
using Tnb.WarehouseMgr.Entities;
namespace Tnb.WarehouseMgr
{
/// <summary>
/// 动态规划类
/// </summary>
public class Dp
{
private const int Max = int.MaxValue;
private int Min = int.MaxValue;
private int Deep = 0;
/// <summary>
/// 动态规划函数
/// </summary>
/// <param name="roads"></param>
/// <param name="sPointId"></param>
/// <param name="ePointId"></param>
/// <returns></returns>
public void DpFunc(List<WmsRoad> roads, List<WmsRoad> subRoads, List<string> pointIds, Dictionary<string, bool> isVisited, string sPointId, string ePointId)
{
Deep++;
var sRoads = roads.FindAll(x => x.startpoint_id == sPointId).ToList();
var sRoads_EPointIds = sRoads.Select(x => x.endpoint_id).ToList();
if (!isVisited[sPointId])
{
Console.WriteLine($"code={roads.Find(x => x.startpoint_id == sPointId).startpoint_code}");
pointIds.Add(sPointId);
}
var eSubRoads = sRoads.FindAll(x => x.endpoint_id == ePointId);
if (eSubRoads?.Count > 0)
{
pointIds.Add(ePointId);
Console.WriteLine($"Deep={Deep}");
foreach (var kvp in isVisited)
{
isVisited[kvp.Key] = true;
}
return;
}
subRoads = roads.FindAll(x => sRoads_EPointIds.Contains(x.startpoint_id)).ToList();
if (subRoads?.Count > 0 && !isVisited[sPointId])
{
isVisited[sPointId] = true;
for (int i = 0; i < subRoads.Count; i++)
{
var sIdx = subRoads[i].startpoint_id;
if (!isVisited[sIdx])
{
DpFunc(roads, subRoads, pointIds, isVisited, sIdx, ePointId);
}
}
}
}
}
}

View File

@@ -30,7 +30,6 @@ using Tnb.Common.Utils;
using Tnb.WarehouseMgr.Entities;
using Tnb.WarehouseMgr.Entities.Consts;
using Tnb.WarehouseMgr.Entities.Dto;
using Tnb.WarehouseMgr.Entities.Dto.Inputs;
using Tnb.WarehouseMgr.Entities.Enums;
using Tnb.WarehouseMgr.Interfaces;
@@ -224,6 +223,31 @@ namespace Tnb.WarehouseMgr
var row = await _db.Insertable(preTasks).ExecuteCommandAsync();
return row > 0;
}
/// <summary>
/// 生成预任务后续处理
/// </summary>
/// <returns></returns>
[NonAction]
public async Task GenTaskHandleAfter(GenPreTaskUpInput input)
{
try
{
await _db.Ado.BeginTranAsync();
//根据载具移入Id回更单据状态
await _db.Updateable<WmsMoveInstock>().SetColumns(it => new WmsMoveInstock { status = WmsWareHouseConst.BILLSTATUS_ON_ID }).Where(it => it.id == input.PreTaskId).ExecuteCommandAsync();
//根据生成的预任务,插入预任务操作记录
await _db.Insertable(input.PreTaskRecords).ExecuteCommandAsync();
//根据载具ID更新是否锁定和赋值起始库位
await _db.Updateable<WmsCarryH>().SetColumns(it => new WmsCarryH { is_lock = 1, location_id = input.CarryStartLocationId, location_code = input.CarryStartLocationCode }).Where(it => it.id == input.CarryId).ExecuteCommandAsync();
//根据所有库位更新库位的锁定状态为“锁定”
await _db.Updateable<BasLocation>().SetColumns(it => new BasLocation { is_lock = 1 }).Where(it => input.LocationIds.Contains(it.id)).ExecuteCommandAsync();
await _db.Ado.CommitTranAsync();
}
catch (Exception)
{
await _db.Ado.RollbackTranAsync();
}
}
/// <summary>
/// 路径算法
@@ -243,34 +267,84 @@ namespace Tnb.WarehouseMgr
private async Task<List<WmsPointH>> LocPathCalcAlgorithms(string pStartId, string pEndId, List<WmsRoad> roads)
{
var points = await _db.Queryable<WmsPointH>().ToListAsync();
var startObj = points.Find(x => x.id == pStartId);
var endObj = points.Find(x => x.id == pEndId);
var sIndex = points.IndexOf(startObj);
var eIndex = points.IndexOf(endObj);
var vexs = points.Select(p => p.id).ToArray();
EData[] edges = new EData[roads.Count];
for (int i = 0; i < edges.Length; i++)
List<WmsPointH> results = new();
List<WmsRoad> subRoads = new();
Dictionary<string, bool> isVisited = roads.Select(x => x.startpoint_id).Distinct().ToDictionary(x => x, x => false);
List<string> pointIds = new();
List<string> codes = new();
Dp dp = new();
dp.DpFunc(roads, subRoads, pointIds, isVisited, pStartId, pEndId);
foreach (var pid in pointIds)
{
var start = roads[i].startpoint_id;
var end = roads[i].endpoint_id;
var weight = roads[i].distance;
edges[i] = new EData(start, end, weight);
var point = points.Find(x => x.id == pid);
results.Add(point);
}
Dijkstra<WmsPointH> pG = new(vexs, edges);
int[] prev = new int[pG.mVexs.Length];
int[] dist = new int[pG.mVexs.Length];
List<WmsPointH> vertexs = new() { startObj };
pG.CalcDijkstra(sIndex, prev, dist);
var pointIds = points.Select(p => p.id).ToList();
List<string> result = new();
GetPoints(pointIds, prev, result, eIndex);
var shortestPathPoints = points.FindAll(x => result.Contains(x.id));
shortestPathPoints.Add(points.Find(x => x.id == pStartId));
List<WmsPointH> results = new() { startObj };
var isVisited = shortestPathPoints.ToDictionary(x => x.id, x => false);
isVisited[pStartId] = true;
MatchPoint(results, roads, shortestPathPoints, isVisited, pStartId, pEndId);
results.Add(endObj);
#region dijkstra
//var points = await _db.Queryable<WmsPointH>().ToListAsync();
//var startObj = points.Find(x => x.id == pStartId);
//var endObj = points.Find(x => x.id == pEndId);
//var sIndex = points.IndexOf(startObj);
//var eIndex = points.IndexOf(endObj);
//if (eIndex < sIndex)
//{
// var tempIndex = sIndex;
// sIndex = eIndex;
// eIndex = tempIndex;
// var temp = points[sIndex];
// points[sIndex] = points[eIndex];
// points[eIndex] = temp;
//}
////MatchPoint(results, roads, shortestPathPoints, isVisited, pStartId, pEndId);
//var vexs = points.Select(p => p.id).ToArray();
//EData[] edges = new EData[roads.Count];
//for (int i = 0; i < edges.Length; i++)
//{
// var start = roads[i].startpoint_id;
// var end = roads[i].endpoint_id;
// var weight = roads[i].distance;
// edges[i] = new EData(start, end, weight);
//}
//Dijkstra pG = new(vexs, edges);
//int[] prev = new int[pG.mVexs.Length];
//int[] dist = new int[pG.mVexs.Length];
//List<WmsPointH> vertexs = new() { startObj };
//pG.CalcDijkstra(sIndex, prev, dist);
//var pointIds = points.Select(p => p.id).ToList();
//List<string> result = new();
//GetPoints(pointIds, prev, result, eIndex);
//var items =new List<string>();
//foreach (var item in prev.Where(x=>x!=0))
//{
// if (points[item] != null)
// {
// items.Add(points[item].point_code);
// }
//}
//var @strings = string.Join(",", items.OrderBy(o=>o));
//var shortestPathPoints = points.FindAll(x => result.Contains(x.id));
//if (shortestPathPoints.IndexOf(startObj) < 0)
//{
// shortestPathPoints.Add(startObj);
//}
//List<WmsPointH> results = new() { startObj };
//var isVisited = shortestPathPoints.ToDictionary(x => x.id, x => false);
//var isVisited2 = shortestPathPoints.ToDictionary(x => x.id, x => false);
//isVisited[pStartId] = true;
//MatchPoint(results, roads, shortestPathPoints, isVisited, pStartId, pEndId);
//results.Add(endObj);
#endregion
return results;
}
/// <summary>
@@ -319,18 +393,18 @@ namespace Tnb.WarehouseMgr
var isOk = false;
try
{
//await _db.Ado.BeginTranAsync();
await _db.Ado.BeginTranAsync();
isOk = await _db.Updateable(entity).ExecuteCommandHasChangeAsync();
if (entities?.Count > 0)
{
var row = await _db.Storageable(entities).ExecuteCommandAsync();
isOk = row > 0;
}
//await _db.Ado.CommitTranAsync();
await _db.Ado.CommitTranAsync();
}
catch (Exception)
{
//await _db.Ado.RollbackTranAsync();
await _db.Ado.RollbackTranAsync();
}
return isOk;
}

View File

@@ -3,14 +3,22 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JNPF.Common.Core.Manager;
using JNPF.Common.Dtos.VisualDev;
using JNPF.Common.Enums;
using JNPF.Common.Extension;
using JNPF.Common.Security;
using JNPF.FriendlyException;
using JNPF.Systems.Interfaces.System;
using JNPF.VisualDev;
using JNPF.VisualDev.Entitys;
using JNPF.VisualDev.Interfaces;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using Tnb.BasicData.Entities;
using Tnb.WarehouseMgr.Entities;
using Tnb.WarehouseMgr.Entities.Consts;
using Tnb.WarehouseMgr.Entities.Dto;
using Tnb.WarehouseMgr.Interfaces;
@@ -27,46 +35,106 @@ namespace Tnb.WarehouseMgr
private readonly IRunService _runService;
private readonly IVisualDevService _visualDevService;
private readonly IWareHouseService _wareHouseService;
private readonly IBillRullService _billRullService;
private readonly IUserManager _userManager;
public WmsCarryMoveInStockService(
ISqlSugarRepository<WmsCarryH> repository,
IRunService runService,
IVisualDevService visualDevService,
IWareHouseService wareHouseService)
IWareHouseService wareHouseService,
IUserManager userManager,
IBillRullService billRullService)
{
_db = repository.AsSugarClient();
_runService = runService;
_visualDevService = visualDevService;
_wareHouseService = wareHouseService;
_userManager = userManager;
_billRullService = billRullService;
OverideFuncs.CreateAsync = CarryMoveIn;
}
private async Task<dynamic> CarryMoveIn(VisualDevModelDataCrInput input)
{
VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(ModuleId, true);
await _runService.Create(templateEntity, input);
//入库取终点
var inStockStrategyInput = new InStockStrategyQuery { warehouse_id = input.data[nameof(InStockStrategyQuery.warehouse_id)].ToString(), Size = 1 };
var endLocations = await _wareHouseService.InStockStrategy(inStockStrategyInput);
WmsPointH sPoint = null;
WmsPointH ePoint = null;
if (input.data.ContainsKey(nameof(WmsPointH.location_id)))
try
{
sPoint = await _db.Queryable<WmsPointH>().FirstAsync(it => it.location_id == input.data[nameof(WmsPointH.location_id)].ToString());
await _db.Ado.BeginTranAsync();
VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(ModuleId, true);
await _runService.Create(templateEntity, input);
//入库取终点
var inStockStrategyInput = new InStockStrategyQuery { warehouse_id = input.data[nameof(InStockStrategyQuery.warehouse_id)].ToString(), Size = 1 };
var endLocations = await _wareHouseService.InStockStrategy(inStockStrategyInput);
WmsPointH sPoint = null;
WmsPointH ePoint = null;
if (input.data.ContainsKey(nameof(WmsPointH.location_id)))
{
sPoint = await _db.Queryable<WmsPointH>().FirstAsync(it => it.location_id == input.data[nameof(WmsPointH.location_id)].ToString());
}
if (endLocations?.Count > 0)
{
ePoint = await _db.Queryable<WmsPointH>().FirstAsync(it => it.location_id == endLocations[0].id);
}
if (sPoint != null && ePoint != null)
{
var points = await _wareHouseService.PathAlgorithms(sPoint.id, ePoint.id);
//根据获取的路径点生成预任务,生成顺序必须预路径算法返回的起终点的顺序一致(预任务顺序)
if (points?.Count > 0)
{
if (points.Count <= 2) throw new AppFriendlyException("该路径不存在", 500);
var preTasks = points.Where(it => !it.location_id.IsNullOrEmpty()).GroupBy(g => g.area_code).Select(it =>
{
var sPoint = it.FirstOrDefault();
var ePoint = it.LastOrDefault();
WmsPretaskH preTask = new();
preTask.org_id = _userManager.User.OrganizeId;
preTask.startlocation_id = sPoint?.location_id;
preTask.startlocation_code = sPoint?.location_code;
preTask.endlocation_id = ePoint?.location_id;
preTask.endlocation_code = ePoint?.location_code;
preTask.start_floor = sPoint?.floor.ToString();
preTask.end_floor = ePoint?.floor.ToString();
preTask.bill_code = _billRullService.GetBillNumber(WmsWareHouseConst.WMS_PRETASK_H_ENCODE).GetAwaiter().GetResult();
preTask.status = WmsWareHouseConst.PRETASK_BILL_STATUS_DXF_ID;
preTask.biz_type = WmsWareHouseConst.BIZTYPE_MOVEIN_ID;
preTask.carry_id = input.data[nameof(preTask.carry_id)]?.ToString()!;
preTask.carry_code = input.data[nameof(preTask.carry_code)]?.ToString()!;
preTask.area_id = sPoint?.area_id;
preTask.area_code = it.Key;
preTask.require_id = input.data["ReturnIdentity"].ToString();
preTask.require_code = input.data[nameof(preTask.bill_code)]?.ToString()!;
preTask.create_id = _userManager.UserId;
preTask.create_time = DateTime.Now;
return preTask;
}).ToList();
var isOk = await _wareHouseService.GenPreTask(preTasks);
if (isOk)
{
var preTaskUpInput = new GenPreTaskUpInput();
preTaskUpInput.PreTaskId = input.data["ReturnIdentity"].ToString();
preTaskUpInput.CarryId = input.data[nameof(WmsCarryD.carry_id)]?.ToString()!;
preTaskUpInput.CarryStartLocationId = points.FirstOrDefault().location_id;
preTaskUpInput.CarryStartLocationCode = points.FirstOrDefault().location_code;
preTaskUpInput.LocationIds = points.Select(x => x.id).ToList();
preTaskUpInput.PreTaskRecords = preTasks.Adapt<List<WmsHandleH>>();
preTaskUpInput.PreTaskRecords.ForEach(x => x.id = SnowflakeIdHelper.NextId());
await _wareHouseService.GenTaskHandleAfter(preTaskUpInput);
}
}
}
await _db.Ado.CommitTranAsync();
}
if (endLocations?.Count > 0)
catch (Exception ex)
{
ePoint = await _db.Queryable<WmsPointH>().FirstAsync(it => it.location_id == endLocations[0].id);
await _db.Ado.RollbackTranAsync();
throw;
}
if (sPoint != null && ePoint != null)
{
var points = await _wareHouseService.PathAlgorithms(sPoint.id, ePoint.id);
//根据获取的路径点生成预任务,生成顺序必须预路径算法返回的起终点的顺序一致(预任务顺序)
//根据载具移入Id回更单据状态
//根据生成的预任务,插入预任务操作记录
//根据载具ID更新是否锁定和赋值起始库位
//根据所有库位更新库位的锁定状态为“锁定”
}
return Task.FromResult(1);
return Task.FromResult(true);
}
}
}

View File

@@ -15,7 +15,7 @@ using SqlSugar;
using Tnb.Common.Utils;
using Tnb.WarehouseMgr.Entities;
using Tnb.WarehouseMgr.Entities.Consts;
using Tnb.WarehouseMgr.Entities.Dto.Inputs;
using Tnb.WarehouseMgr.Entities.Dto;
using Tnb.WarehouseMgr.Entities.Enums;
using Tnb.WarehouseMgr.Interfaces;

View File

@@ -23,11 +23,9 @@ namespace Tnb.WarehouseMgr
/// <summary>
/// 路径管理业务类
/// </summary>
[ApiDescriptionSettings(Tag = ModuleConsts.Tag, Area = ModuleConsts.Area, Order = 700)]
[Route("api/[area]/[controller]/[action]")]
[OverideVisualDev(ModuleId)]
public class WmsRouteMgrService : IOverideVisualDevService, IWmsRouteMgrService, IDynamicApiController, ITransient
public class WmsRouteMgrService : BaseWareHouseService, IWmsRouteMgrService
{
private const string ModuleId = "26100621140773";
private readonly ISqlSugarClient _db;

View File

@@ -11,13 +11,13 @@ namespace Tnb.Common.Utils
/// <summary>
/// 迪杰斯特拉(最短路径算法)
/// </summary>
public class Dijkstra<T> where T : BaseEntity<string>, new()
public class Dijkstra
{
public static int MAX = int.MaxValue;
public int mEdgNum; // 边的数量
public VNode[] mVexs; // 顶点数组
private EData[] edges; //边的数组
/*
* 创建图
*
@@ -27,7 +27,7 @@ namespace Tnb.Common.Utils
*/
public Dijkstra(string[] vexs, EData[] edges)
{
this.edges = edges;
// 初始化"顶点数"和"边数"
int vlen = vexs.Length;
int elen = edges.Length;
@@ -142,7 +142,7 @@ namespace Tnb.Common.Utils
// 对"起点D"自身进行初始化
flag[vs] = true;
dist[vs] = 0;
HashSet<int> set = new();
// 遍历mVexs.Length-1次每次找出一个顶点的最短路径。
int k = 0;
for (int i = 1; i < mVexs.Length; i++)
@@ -154,9 +154,12 @@ namespace Tnb.Common.Utils
{
if (flag[j] == false && dist[j] < min)
{
min = dist[j];
k = j;
set.Add(j);
}
}
// 标记"顶点k"为已经获取到最短路径
flag[k] = true;
@@ -173,14 +176,6 @@ namespace Tnb.Common.Utils
}
}
}
// 打印dijkstra最短路径的结果
//Console.WriteLine("dijkstra({0}): \n", mVexs[vs].data);
//for (int i = 0; i < mVexs.Length; i++)
//{
// Console.WriteLine("shortest({0}, {1})={2}\n", mVexs[vs].data, mVexs[i].data, dist[i]);
//}
//return vertexs;
}
}
@@ -189,8 +184,17 @@ namespace Tnb.Common.Utils
/// </summary>
public class ENode
{
/// <summary>
/// 该边所指向的顶点的位置
/// </summary>
public int ivex; // 该边所指向的顶点的位置
/// <summary>
/// 该边的权
/// </summary>
public int weight; // 该边的权
/// <summary>
/// 指向下一条弧的指针
/// </summary>
public ENode nextEdge; // 指向下一条弧的指针
}