路径算法调整为动态规划方式,新增预任务申请功能
This commit is contained in:
@@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,5 +16,7 @@ namespace Tnb.WarehouseMgr
|
||||
public class BaseWareHouseService : IOverideVisualDevService, IDynamicApiController, ITransient
|
||||
{
|
||||
public OverideVisualDevFunc OverideFuncs { get; } = new OverideVisualDevFunc();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
215
WarehouseMgr/Tnb.WarehouseMgr/Dijkstra.cs
Normal file
215
WarehouseMgr/Tnb.WarehouseMgr/Dijkstra.cs
Normal 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;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
69
WarehouseMgr/Tnb.WarehouseMgr/Dp.cs
Normal file
69
WarehouseMgr/Tnb.WarehouseMgr/Dp.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; // 指向下一条弧的指针
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user