735 lines
32 KiB
C#
735 lines
32 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Dynamic;
|
||
using System.Linq;
|
||
using System.Linq.Expressions;
|
||
using System.Reflection;
|
||
using System.Runtime.InteropServices;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using Aop.Api.Domain;
|
||
using Aspose.Cells.Drawing;
|
||
using Dm;
|
||
using JNPF.Common.Contracts;
|
||
using JNPF.Common.Core.Manager;
|
||
using JNPF.Common.Enums;
|
||
using JNPF.Common.Extension;
|
||
using JNPF.Common.Security;
|
||
using JNPF.DependencyInjection;
|
||
using JNPF.DynamicApiController;
|
||
using JNPF.Extras.CollectiveOAuth.Config;
|
||
using JNPF.FriendlyException;
|
||
using JNPF.Systems.Entitys.Dto.Module;
|
||
using JNPF.Systems.Interfaces.System;
|
||
using Mapster;
|
||
using Microsoft.AspNetCore.Hosting;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Microsoft.CodeAnalysis;
|
||
using NPOI.OpenXmlFormats.Wordprocessing;
|
||
using Polly.Timeout;
|
||
using Senparc.Weixin.Work.AdvancedAPIs.OaDataOpen;
|
||
using Spire.Pdf.Widget;
|
||
using SqlSugar;
|
||
using Tnb.BasicData.Entities;
|
||
using Tnb.BasicData.Entities.Enums;
|
||
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;
|
||
|
||
namespace Tnb.WarehouseMgr
|
||
{
|
||
/// <summary>
|
||
/// 库房业务类(出入库)
|
||
/// </summary>
|
||
public class WareHouseService : BaseWareHouseService, IWareHouseService
|
||
{
|
||
private readonly ISqlSugarClient _db;
|
||
private readonly IDictionaryDataService _dictionaryDataService;
|
||
private readonly IBillRullService _billRullService;
|
||
private readonly IUserManager _userManager;
|
||
public WareHouseService(ISqlSugarRepository<WmsInstockH> repository, IDictionaryDataService dictionaryDataService, IBillRullService billRullService, IUserManager userManager)
|
||
{
|
||
_db = repository.AsSugarClient();
|
||
_dictionaryDataService = dictionaryDataService;
|
||
_billRullService = billRullService;
|
||
_userManager = userManager;
|
||
}
|
||
/// <summary>
|
||
/// 根据载具Id带出库位、仓库信息
|
||
/// </summary>
|
||
/// <param name="carryId">载具id</param>
|
||
/// <remarks>
|
||
/// returns:
|
||
/// <br/>{
|
||
/// <br/> carry_id:载具Id
|
||
/// <br/> carry_name:载具名称
|
||
/// <br/> location_id:库位Id
|
||
/// <br/> location_name:库位名称
|
||
/// <br/> warehouse_id:库房Id
|
||
/// <br/> warehouse_name:库房名称
|
||
/// <br/>}
|
||
/// </remarks>
|
||
[HttpGet]
|
||
public async Task<dynamic> GetLocationAndWorkHouseByCarryId([FromRoute] string carryId)
|
||
{
|
||
var items = await _db.Queryable<WmsCarryH>().LeftJoin<BasLocation>((a, b) => a.location_id == b.id)
|
||
.LeftJoin<BasWarehouse>((a, b, c) => b.wh_id == c.id)
|
||
.Where(a => a.id == carryId)
|
||
.Select((a, b, c) => new
|
||
{
|
||
carry_id = a.id,
|
||
carry_name = a.carry_name,
|
||
location_id = b.id,
|
||
|
||
location_name = b.location_name,
|
||
warehouse_id = c.id,
|
||
warehouse_name = c.whname,
|
||
})
|
||
.ToListAsync();
|
||
return items;
|
||
}
|
||
/// <summary>
|
||
/// 库房业务,入库、出库申请新增修改功能
|
||
/// </summary>
|
||
/// <param name="input"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task ApplyFor(InOutStockApplyforUpInput input)
|
||
{
|
||
// bill_line,location_id,delivery_date,carry_id,carry_code
|
||
if (input == null) throw new ArgumentNullException("input");
|
||
var isOk = false;
|
||
switch (input.inoutStockType)
|
||
{
|
||
case EnumInOutStockType.In:
|
||
var wmsInstockD = input.Adapt<WmsInstockD>();
|
||
var wmsInstockCodes = input.InstockCodes.Adapt<List<WmsInstockCode>>();
|
||
if (wmsInstockCodes?.Count > 0)
|
||
{
|
||
wmsInstockCodes.ForEach(x =>
|
||
{
|
||
if (x.id.IsNullOrWhiteSpace())
|
||
{
|
||
x.id = SnowflakeIdHelper.NextId();
|
||
}
|
||
x.bill_d_id = wmsInstockD.id;
|
||
});
|
||
}
|
||
isOk = await _update(wmsInstockD, wmsInstockCodes);
|
||
break;
|
||
case EnumInOutStockType.Out:
|
||
var wmsOutstockD = input.Adapt<WmsOutstockD>();
|
||
var wmsOutstockCodes = input.InstockCodes.Adapt<List<WmsOutstockCode>>();
|
||
if (wmsOutstockCodes?.Count > 0)
|
||
{
|
||
wmsOutstockCodes.ForEach(x =>
|
||
{
|
||
if (x.id.IsNullOrWhiteSpace())
|
||
{
|
||
x.id = SnowflakeIdHelper.NextId();
|
||
}
|
||
x.bill_d_id = wmsOutstockD.id;
|
||
});
|
||
}
|
||
isOk = await _update(wmsOutstockD, wmsOutstockCodes);
|
||
break;
|
||
}
|
||
if (!isOk) throw Oops.Oh(ErrorCode.COM1001);
|
||
}
|
||
/// <summary>
|
||
/// 根据明细Id获取出入库明细信息
|
||
/// </summary>
|
||
/// <param name="billDId"></param>
|
||
/// <returns></returns>
|
||
[HttpGet]
|
||
public async Task<dynamic> GetInOutStockCodesById([FromQuery] InOutStockDetailQuery input)
|
||
{
|
||
dynamic result = null;
|
||
var dic = await _dictionaryDataService.GetDictionaryByTypeId(WmsWareHouseConst.WMS_INSTOCK_D_BILL_STATUS_TYPEID);
|
||
switch (input.inoutStockType)
|
||
{
|
||
case EnumInOutStockType.In:
|
||
result = await _db.Queryable<WmsInstockD>()
|
||
.Where(a => a.id == input.bill_d_id)
|
||
.Select(a => new InStockDetailOutput
|
||
{
|
||
id = a.id,
|
||
bill_id = a.bill_id,
|
||
unit_id = a.unit_id,
|
||
code_batch = a.code_batch,
|
||
warehouse_id = a.warehouse_id,
|
||
line_status = a.line_status,
|
||
reason = a.reason,
|
||
pr_qty = a.pr_qty,
|
||
qty = a.qty,
|
||
price = a.price,
|
||
tax_price = a.tax_price,
|
||
print_qty = a.print_qty,
|
||
scan_qty = a.scan_qty,
|
||
material_code = a.material_code,
|
||
amount = a.amount,
|
||
all_amount = a.all_amount,
|
||
CodeDetails = SqlFunc.Subqueryable<WmsInstockCode>().Where(it => it.bill_d_id == a.id).ToList(),
|
||
})
|
||
.Mapper(it => it.line_status = dic.ContainsKey(it.line_status) ? dic[it.line_status]?.ToString()! : "")
|
||
.ToListAsync();
|
||
|
||
break;
|
||
case EnumInOutStockType.Out:
|
||
result = await _db.Queryable<WmsOutstockD>()
|
||
.Where(a => a.id == input.bill_d_id)
|
||
.Select(a => new OutStockDetailOutput
|
||
{
|
||
id = a.id,
|
||
bill_id = a.bill_id,
|
||
unit_id = a.unit_id,
|
||
code_batch = a.code_batch,
|
||
warehouse_id = a.warehouse_id,
|
||
line_status = a.line_status,
|
||
price = a.price,
|
||
tax_price = a.tax_price,
|
||
material_code = a.material_code,
|
||
amount = a.amount,
|
||
all_amount = a.all_amount,
|
||
CodeDetails = SqlFunc.Subqueryable<WmsOutstockCode>().Where(it => it.bill_d_id == a.id).ToList(),
|
||
})
|
||
.Mapper(it => it.line_status = dic.ContainsKey(it.line_status) ? dic[it.line_status]?.ToString()! : "")
|
||
.ToListAsync();
|
||
break;
|
||
}
|
||
return result;
|
||
}
|
||
/// <summary>
|
||
/// 入库策略
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpGet]
|
||
public async Task<List<BasLocation>> InStockStrategy([FromQuery] InStockStrategyQuery input)
|
||
{
|
||
var items = new List<BasLocation>();
|
||
try
|
||
{
|
||
|
||
//var stauts = (int)EnumCarryStatus.空闲;
|
||
items = await _db.Queryable<BasLocation>().Where(it => it.wh_id == input.warehouse_id && it.is_lock == 0 && it.is_type == "0" && it.is_use == (int)EnumCarryStatus.空闲).OrderBy(it => new { it.layers, it.loc_line, it.loc_column }, OrderByType.Asc).ToListAsync();
|
||
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
|
||
throw;
|
||
}
|
||
return items.Take(input.Size).ToList();
|
||
}
|
||
/// <summary>
|
||
/// 出库策略
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpGet]
|
||
public async Task<dynamic> OutStockStrategy()
|
||
{
|
||
return Task.FromResult<dynamic>(true);
|
||
}
|
||
/// <summary>
|
||
/// 生成任务执行
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task GenTaskExecute()
|
||
{
|
||
//任务链属性处理内部函数
|
||
async Task _taskChainAttrHandle(List<WmsDistaskH> items, List<WmsPretaskH> areaPreTasks, int moveNum)
|
||
{
|
||
await Task.Run(() =>
|
||
{
|
||
if (moveNum == 1 || (moveNum > areaPreTasks.Count && areaPreTasks.Count == 1))
|
||
{
|
||
items.ForEach(x =>
|
||
{
|
||
x.is_chain = 0;
|
||
|
||
});
|
||
}
|
||
else if ((moveNum > areaPreTasks.Count && areaPreTasks.Count > 1) || moveNum < areaPreTasks.Count)
|
||
{
|
||
items.ForEach(x => x.is_chain = 1);
|
||
//items[0].chain_type = "1";
|
||
//for (int i = 0; i < items.Count; i++)
|
||
//{
|
||
// if (i == 0 || i == items.Count - 1) continue;
|
||
// items[i].chain_type = "2";
|
||
//}
|
||
//items[^1].chain_type = "3";
|
||
}
|
||
});
|
||
|
||
}
|
||
|
||
//获取所有未下发的预任务申请
|
||
var preTasks = await _db.Queryable<WmsPretaskH>().InnerJoin<WmsCarryH>((a, b) => a.startlocation_id == b.location_id)
|
||
.InnerJoin<WmsAreaH>((a, b, c) => a.area_id == c.id)
|
||
.Where(a => a.status == WmsWareHouseConst.PRETASK_BILL_STATUS_DXF_ID)
|
||
.OrderBy(a => new { priority = SqlFunc.Desc(a.priority), a.bill_code })
|
||
.Select((a, b, c) => new WmsPretaskH
|
||
{
|
||
move_num = c.move_num
|
||
}, true)
|
||
.ToListAsync();
|
||
if (preTasks.Count > 0)
|
||
{
|
||
//根据预任务管理区分组,获取到所有分组后的预任务,遍历每个预任务 是否为任务链,通过管理区ID
|
||
var preTaskGroups = preTasks.GroupBy(g => g.area_code).ToList();
|
||
List<WmsDistaskH> disTasks = new();
|
||
foreach (var itGroup in preTaskGroups)
|
||
{
|
||
var moveNum = itGroup.First().move_num;
|
||
var items = itGroup.Adapt<List<WmsDistaskH>>();
|
||
items.ForEach(x =>
|
||
{
|
||
x.status = WmsWareHouseConst.TASK_BILL_STATUS_DZX_ID;
|
||
x.bill_code = _billRullService.GetBillNumber(WmsWareHouseConst.WMS_TASK_EXECUTE_ENCODE).GetAwaiter().GetResult();
|
||
});
|
||
var areaPreTasks = itGroup.ToList();
|
||
if (moveNum == 1)
|
||
{
|
||
items.ForEach(x =>
|
||
{
|
||
x.is_chain = 0;
|
||
x.chain_type = "3";
|
||
});
|
||
}
|
||
else if (moveNum > 1)
|
||
{
|
||
//搬运数量==预任务数,可以生成任务执行,为任务链
|
||
if (moveNum == areaPreTasks.Count)
|
||
{
|
||
await _taskChainAttrHandle(items, areaPreTasks, moveNum);
|
||
}
|
||
else if (moveNum > areaPreTasks.Count && areaPreTasks.Count == 1) //搬运数量>预任务数,且预任务数等于1,不是任务链,预任务数据平替到任务执行
|
||
{
|
||
await _taskChainAttrHandle(items, areaPreTasks, moveNum);
|
||
}
|
||
else if (moveNum > areaPreTasks.Count && areaPreTasks.Count > 1) //搬运数量>预任务数,且预任务数大于1,可以执行时,可以生成任务执行,为任务链
|
||
{
|
||
await _taskChainAttrHandle(items, areaPreTasks, moveNum);
|
||
}
|
||
else if (false) //搬运数量>预任务数,且预任务数大于1,不可以执行时,先空着
|
||
{
|
||
}
|
||
else if (moveNum < areaPreTasks.Count) //搬运数量<预任务数, 按照预任务先后顺序,生成对应搬运数量的任务组
|
||
{
|
||
await _taskChainAttrHandle(items, areaPreTasks, moveNum);
|
||
}
|
||
}
|
||
disTasks.AddRange(items);
|
||
}
|
||
try
|
||
{
|
||
await _db.Ado.BeginTranAsync();
|
||
|
||
disTasks.ForEach(x => x.id = SnowflakeIdHelper.NextId());
|
||
var row = await _db.Insertable(disTasks).ExecuteCommandAsync();
|
||
if (row > 0)
|
||
{
|
||
var preTaskIds = preTasks.Select(x => x.id).ToList();
|
||
row = await _db.Updateable<WmsPretaskH>().SetColumns(it => new WmsPretaskH { status = WmsWareHouseConst.PRETASK_BILL_STATUS_YXF_ID }).Where(it => preTaskIds.Contains(it.id)).ExecuteCommandAsync();
|
||
}
|
||
|
||
await _db.Ado.CommitTranAsync();
|
||
}
|
||
catch (Exception)
|
||
{
|
||
await _db.Ado.RollbackTranAsync();
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 任务执行
|
||
/// </summary>
|
||
/// <param name="input"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task TaskExecute(TaskExecuteUpInput input)
|
||
{
|
||
try
|
||
{
|
||
await _db.Ado.BeginTranAsync();
|
||
|
||
//更任务执行
|
||
for (int i = 0, cnt = input.disTaskIds.Count; i < cnt; i++)
|
||
{
|
||
if (input.EqpIds?.Count > 0)
|
||
{
|
||
await _db.Updateable<WmsDistaskH>().SetColumns(it => new WmsDistaskH { status = WmsWareHouseConst.TASK_BILL_STATUS_YXD_ID, device_id = input.EqpIds[i] }).Where(it => input.disTaskIds.Contains(it.id)).ExecuteCommandAsync();
|
||
}
|
||
else
|
||
{
|
||
await _db.Updateable<WmsDistaskH>().SetColumns(it => new WmsDistaskH { status = WmsWareHouseConst.TASK_BILL_STATUS_YXD_ID }).Where(it => input.disTaskIds.Contains(it.id)).ExecuteCommandAsync();
|
||
|
||
}
|
||
//await _db.Updateable<WmsDistaskH>().SetColumns(it => setColVal).Where(it => input.disTaskIds.Contains(it.id)).ExecuteCommandAsync();
|
||
}
|
||
var preTaskIds = await _db.Queryable<WmsDistaskH>().Where(it => input.disTaskIds.Contains(it.id)).Select(it => it.pretask_id).ToListAsync();
|
||
if (preTaskIds.Count > 0)
|
||
{
|
||
//更预任务申请表状态
|
||
await _db.Updateable<WmsPretaskH>().SetColumns(it => new WmsPretaskH { status = WmsWareHouseConst.PRETASK_BILL_STATUS_START_ID }).Where(it => preTaskIds.Contains(it.id)).ExecuteCommandAsync();
|
||
}
|
||
|
||
await _db.Ado.CommitTranAsync();
|
||
}
|
||
catch (Exception)
|
||
{
|
||
await _db.Ado.RollbackTranAsync();
|
||
throw;
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 任务执行取操作返回(后续操作)
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task TaskExecuteAfter(TaskExecuteAfterUpInput input)
|
||
{
|
||
//更新任务执行表单据状态
|
||
try
|
||
{
|
||
await _db.Ado.BeginTranAsync();
|
||
|
||
await _db.Updateable<WmsDistaskH>().SetColumns(it => new WmsDistaskH { status = WmsWareHouseConst.TASK_BILL_STATUS_RUNING_ID }).Where(it => input.disTaskIds.Contains(it.id)).ExecuteCommandAsync();
|
||
//清空载具库位数据
|
||
var carryIds = await _db.Queryable<WmsDistaskH>().Where(it => input.disTaskIds.Contains(it.id)).Select(it => it.carry_id).ToListAsync();
|
||
if (carryIds?.Count > 0)
|
||
{
|
||
await _db.Updateable<WmsCarryH>().SetColumns(it => new WmsCarryH { location_id = null, location_code = null }).Where(it => carryIds.Contains(it.id)).ExecuteCommandAsync();
|
||
}
|
||
var startLocationIds = await _db.Queryable<WmsDistaskH>().Where(it => input.disTaskIds.Contains(it.id)).Select(it => it.startlocation_id).ToListAsync();
|
||
//更新起始库位,状态改为空闲、锁定状态,未锁定
|
||
if (startLocationIds?.Count > 0)
|
||
{
|
||
await _db.Updateable<BasLocation>().SetColumns(it => new BasLocation { is_use = (int)EnumCarryStatus.空闲, is_lock = 0 }).Where(it => startLocationIds.Contains(it.id)).ExecuteCommandAsync();
|
||
}
|
||
|
||
await _db.Ado.CommitTranAsync();
|
||
}
|
||
catch (Exception)
|
||
{
|
||
await _db.Ado.RollbackTranAsync();
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 任务完成
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task TaskComplate(TaskCompleUpInput input)
|
||
{
|
||
try
|
||
{
|
||
await _db.Ado.BeginTranAsync();
|
||
|
||
//更新任务执行表,单据状态为 完成
|
||
await _db.Updateable<WmsDistaskH>().SetColumns(it => new WmsDistaskH { status = WmsWareHouseConst.TASK_BILL_STATUS_COMPLE_ID }).Where(it => input.disTaskIds.Contains(it.id)).ExecuteCommandAsync();
|
||
//更新预任务申请表,单据状态为 已完成
|
||
var disTasks = await _db.Queryable<WmsDistaskH>().InnerJoin<WmsCarryH>((a, b) => a.carry_id == b.id).Where(a => input.disTaskIds.Contains(a.id)).Select((a, b) => new WmsDistaskH { carry_status = b.carry_status }, true).ToListAsync();
|
||
if (disTasks?.Count > 0)
|
||
{
|
||
var preTaskIds = disTasks.Select(x => x.pretask_id).ToList();
|
||
await _db.Updateable<WmsPretaskH>().SetColumns(it => new WmsPretaskH { status = WmsWareHouseConst.PRETASK_BILL_STATUS_COMPLE_ID }).Where(it => preTaskIds.Contains(it.id)).ExecuteCommandAsync();
|
||
}
|
||
//更新载具,锁定状态为未锁定,更新载具的库位当前任务的目标库位
|
||
if (disTasks?.Count > 0)
|
||
{
|
||
var multiList = disTasks.Select(it => (it.carry_id, it.endlocation_id, it.endlocation_code)).ToList();
|
||
for (int i = 0; i < multiList.Count; i++)
|
||
{
|
||
await _db.Updateable<WmsCarryH>().SetColumns(it => new WmsCarryH { is_lock = 0, location_id = multiList[i].endlocation_id, location_code = multiList[i].endlocation_code }).Where(it => it.id == multiList[i].carry_id).ExecuteCommandAsync();
|
||
}
|
||
}
|
||
//更新库位信息,使用状态为 使用,锁定状态为未锁定
|
||
if (disTasks?.Count > 0)
|
||
{
|
||
var destLocIds = disTasks.Select(it => it.endlocation_id).ToList();
|
||
var multis = disTasks.Select(it => (it.endlocation_id, it.carry_status)).ToList();
|
||
for (int i = 0; i < multis.Count; i++)
|
||
{
|
||
var carryStatus = multis[i].carry_status;
|
||
if (multis[i].carry_status == (int)EnumCarryStatus.空闲)
|
||
{
|
||
carryStatus = (int)EnumCarryStatus.空闲;
|
||
}
|
||
await _db.Updateable<BasLocation>().SetColumns(it => new BasLocation { is_use = carryStatus, is_lock = 0 }).Where(it => it.id == multis[i].endlocation_id).ExecuteCommandAsync();
|
||
}
|
||
//更新业务主表的单据状态
|
||
if (disTasks?.Count > 0)
|
||
{
|
||
foreach (var dt in disTasks)
|
||
{
|
||
var disTaskCodes = await _db.Queryable<WmsDistaskCode>().Where(it => it.bill_id == dt.id).ToListAsync();
|
||
var upInput = new WareHouseUpInput { bizTypeId = dt.biz_type, requireId = dt.require_id, distaskCodes = disTaskCodes, carryIds = disTasks.Select(x => x.carry_id).ToList() };
|
||
upInput.loginType = !_userManager.LoginType.IsNullOrEmpty() ? "app" : "web";
|
||
if (dt.is_sign == 1 && dt.chain_type == "3")
|
||
{
|
||
await DoUpdate(upInput);
|
||
}
|
||
}
|
||
}
|
||
|
||
await _db.Ado.CommitTranAsync();
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
await _db.Ado.RollbackTranAsync();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 生成预任务
|
||
/// </summary>
|
||
/// <param name="preTasks">预任务集合</param>
|
||
/// <param name="preTaskCodes">预任务编码集合</param>
|
||
/// <returns></returns>
|
||
public async Task<bool> GenPreTask(List<WmsPretaskH> preTasks, List<WmsPretaskCode> preTaskCodes)
|
||
{
|
||
var grpList = preTasks.OrderBy(o => o.bill_code).GroupBy(g => g.carry_id).ToList();
|
||
if (grpList?.Count > 0)
|
||
{
|
||
foreach (var grp in grpList)
|
||
{
|
||
var arr = grp.ToArray();
|
||
if (arr.Length > 1)
|
||
{
|
||
var subArr = arr[..^1];
|
||
Array.ForEach(subArr, a => a.chain_type = "1");
|
||
}
|
||
}
|
||
}
|
||
var row = await _db.Insertable(preTasks).ExecuteCommandAsync();
|
||
if (preTaskCodes?.Count > 0)
|
||
{
|
||
row = await _db.Insertable(preTaskCodes).ExecuteCommandAsync();
|
||
}
|
||
return row > 0;
|
||
}
|
||
/// <summary>
|
||
/// 生成预任务后续处理
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[NonAction]
|
||
public async Task GenInStockTaskHandleAfter(GenPreTaskUpInput input, Expression<Func<WmsCarryH, WmsCarryH>> setCarryColumnsExp, Expression<Func<BasLocation, BasLocation>> setLocaionColumbExp)
|
||
{
|
||
try
|
||
{
|
||
await _db.Ado.BeginTranAsync();
|
||
//根据生成的预任务,插入预任务操作记录
|
||
if (input.PreTaskRecord != null)
|
||
{
|
||
await _db.Insertable(input.PreTaskRecord).ExecuteCommandAsync();
|
||
}
|
||
if (input.PreTaskHandleCodes.Count > 0)
|
||
{
|
||
await _db.Insertable(input.PreTaskHandleCodes).ExecuteCommandAsync();
|
||
}
|
||
//根据载具ID,更新是否锁定和赋值起始库位
|
||
if (setCarryColumnsExp != null)
|
||
{
|
||
if (input.CarryIds?.Count > 0)
|
||
{
|
||
await _db.Updateable<WmsCarryH>().SetColumns(setCarryColumnsExp).Where(it => input.CarryIds.Contains(it.id)).ExecuteCommandAsync();
|
||
}
|
||
else
|
||
{
|
||
await _db.Updateable<WmsCarryH>().SetColumns(setCarryColumnsExp).Where(it => it.id == input.CarryId).ExecuteCommandAsync();
|
||
}
|
||
}
|
||
|
||
//根据所有库位更新库位的锁定状态为“锁定”
|
||
if (setLocaionColumbExp != null)
|
||
{
|
||
await _db.Updateable<BasLocation>().SetColumns(setLocaionColumbExp).Where(it => input.LocationIds.Contains(it.id)).ExecuteCommandAsync();
|
||
}
|
||
await _db.Ado.CommitTranAsync();
|
||
}
|
||
catch (Exception)
|
||
{
|
||
await _db.Ado.RollbackTranAsync();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 路径算法
|
||
/// </summary>
|
||
/// <param name="pStartId"></param>
|
||
/// <param name="pEndId"></param>
|
||
/// <returns></returns>
|
||
[NonAction]
|
||
public async Task<List<WmsPointH>> PathAlgorithms(string pStartId, string pEndId)
|
||
{
|
||
var roads = await _db.Queryable<WmsRoad>().ToListAsync();
|
||
var points = await LocPathCalcAlgorithms(pStartId, pEndId, roads);
|
||
return points;
|
||
}
|
||
|
||
#region PrivateMethods
|
||
|
||
private async Task<List<WmsPointH>> LocPathCalcAlgorithms(string pStartId, string pEndId, List<WmsRoad> roads)
|
||
{
|
||
var points = await _db.Queryable<WmsPointH>().ToListAsync();
|
||
List<WmsPointH> results = 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();
|
||
dynamic obj = new ExpandoObject();
|
||
obj.isArrivedEpoint = false;
|
||
dp.DpFunc(roads, pointIds, isVisited, pStartId, pEndId, obj);
|
||
foreach (var pid in pointIds)
|
||
{
|
||
var point = points.Find(x => x.id == pid);
|
||
if (point != null)
|
||
{
|
||
results.Add(point);
|
||
}
|
||
}
|
||
return results;
|
||
|
||
#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
|
||
|
||
}
|
||
/// <summary>
|
||
/// 获取匹配的最短路径节点
|
||
/// </summary>
|
||
/// <param name="results"></param>
|
||
/// <param name="roads"></param>
|
||
/// <param name="shortestPathPoints"></param>
|
||
/// <param name="isVisited"></param>
|
||
/// <param name="pStartId"></param>
|
||
/// <param name="pEndId"></param>
|
||
private void MatchPoint(List<WmsPointH> results, List<WmsRoad> roads, List<WmsPointH> shortestPathPoints, Dictionary<string, bool> isVisited, string pStartId, string pEndId)
|
||
{
|
||
var sRoads = roads.Where(x => x.startpoint_id == pStartId).ToList();
|
||
for (int j = 0; j < sRoads.Count; j++)
|
||
{
|
||
var sPoint = shortestPathPoints.Find(x => x.id == sRoads[j].endpoint_id);
|
||
if (sPoint != null && isVisited.ContainsKey(sPoint.id) && !isVisited[sPoint.id] && sPoint.id != pEndId)
|
||
{
|
||
var code = sPoint.point_code;
|
||
results.Add(sPoint);
|
||
isVisited[sPoint.id] = true;
|
||
MatchPoint(results, roads, shortestPathPoints, isVisited, sPoint.id, pEndId);
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 根据终止节点获取最短路径顶点
|
||
/// </summary>
|
||
/// <param name="pointIds"></param>
|
||
/// <param name="prev"></param>
|
||
/// <param name="result"></param>
|
||
/// <param name="eIdx"></param>
|
||
private static void GetPoints(List<string> pointIds, int[] prev, List<string> result, int eIdx)
|
||
{
|
||
var index = eIdx;
|
||
while (index != 0)
|
||
{
|
||
result.Add(pointIds[index]);
|
||
index = prev[index];
|
||
}
|
||
}
|
||
|
||
private async Task<bool> _update<T1, T2>(T1 entity, List<T2> entities) where T1 : BaseEntity<string>, new() where T2 : BaseEntity<string>, new()
|
||
{
|
||
var isOk = false;
|
||
try
|
||
{
|
||
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();
|
||
}
|
||
catch (Exception)
|
||
{
|
||
await _db.Ado.RollbackTranAsync();
|
||
}
|
||
return isOk;
|
||
}
|
||
|
||
|
||
#endregion
|
||
}
|
||
}
|