同步交互任务代码

dev
嵇文龙 4 weeks ago
parent ca43d74c34
commit b27e4490ee

@ -1560,6 +1560,10 @@ public static class MultiLanguageConst
public const string DuplicateStepType = "Duplicate_Step_Type";
[Description("此任务尚有未完成的子任务或前置条件")]
public const string UnfinishedItems = "Unfinished_Items";
[Description("步骤类型和名称至少指定一项")]
public const string TypeOrName = "TypeOrName";
[Description("此任务尚有未完成的优先级别更高的子任务或前置条件")]
public const string HigherUnfinishedItems = "Higher_Unfinished_Items";
#endregion
#region 任务台相关

@ -509,6 +509,11 @@ public class ClientInfoReq
/// 是否冻结
/// </summary>
public bool IsFrozen { get; set; }
/// <summary>
/// 账单抬头
/// </summary>
public string? BillHeader { get; set; }
}
/// <summary>

@ -442,6 +442,11 @@ public class ClientInfoRes
/// </summary>
public bool IsFrozen { get; set; }
/// <summary>
/// 账单抬头
/// </summary>
public string? BillHeader { get; set; }
/// <summary>
/// 默认联系人
/// </summary>

@ -448,6 +448,12 @@ public class InfoClient : SharedOrgModel<long>
[SugarColumn(ColumnDescription = "是否冻结")]
public bool IsFrozen { get; set; }
/// <summary>
/// 账单抬头
/// </summary>
[SugarColumn(ColumnDescription = "账单抬头", Length = 500, IsNullable = true)]
public string? BillHeader { get; set; }
/// <summary>
/// 客户属性
/// </summary>
@ -469,7 +475,6 @@ public class InfoClient : SharedOrgModel<long>
/// <summary>
/// 干系人列表
/// </summary>
//[SqlSugar.SugarColumn(IsIgnore = true)]
[Navigate(NavigateType.OneToMany, nameof(InfoClientStakeholder.ClientId))]
public List<InfoClientStakeholder>? Stakeholders { get; set; }

@ -1,5 +1,6 @@
using DS.Module.Core;
using DS.WMS.Core.HangfireJob.Dtos;
using DS.WMS.Core.Info.Entity;
using DS.WMS.Core.Op.Entity;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
@ -83,11 +84,12 @@ namespace DS.WMS.Core.QuarztJobs
};
var list = await tenantDb.Queryable<SeaExport>().Where(x => x.SourceCode == SOURCE_CODE && SqlFunc.Between(x.ETD, startDate, endDate) && !x.Deleted)
.Select(x => new
.InnerJoin<InfoClient>((x, y) => x.CustomerId == y.Id)
.Select((x, y) => new
{
x.Id,
x.CustomerId,
x.CustomerName,
EnName = SqlFunc.IsNull(y.EnFullName, y.EnShortName),
x.ETD,
x.TEU
}).ToListAsync();
@ -104,10 +106,10 @@ namespace DS.WMS.Core.QuarztJobs
x.TEU
}).ToListAsync();
model.List = list.GroupBy(x => new { x.CustomerId, x.CustomerName }).Select(x => new WSLItem
model.List = list.GroupBy(x => new { x.CustomerId, x.EnName }).Select(x => new WSLItem
{
CustomerId = x.Key.CustomerId,
CustomerName = x.Key.CustomerName,
CustomerName = x.Key.EnName,
Date = model.Date,
YesterdayTeu = x.Where(x => x.ETD >= yesterday && x.ETD <= yesterday).Sum(x => x.TEU),
TodayTeu = x.Where(x => x.ETD >= today && x.ETD <= today).Sum(x => x.TEU),

@ -71,11 +71,11 @@ namespace DS.WMS.Core.TaskInteraction.Dtos
/// <returns></returns>
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (BusinessId == 0 && (Ids == null || Ids.Length == 0))
{
yield return new ValidationResult($"参数 {nameof(BusinessId)} 与 {nameof(Ids)} 至少指定一项");
}
else if (string.IsNullOrEmpty(TaskTypeName))
//if (BusinessId == 0 && (Ids == null || Ids.Length == 0))
//{
// yield return new ValidationResult($"参数 {nameof(BusinessId)} 与 {nameof(Ids)} 至少指定一项");
//}
if (string.IsNullOrEmpty(TaskTypeName))
{
yield return new ValidationResult($"参数 {nameof(TaskTypeName)} 不能为空");
}

@ -1,5 +1,4 @@
using DS.WMS.Core.TaskInteraction.Entity;
using SqlSugar;
namespace DS.WMS.Core.TaskInteraction.Dtos
{
@ -8,28 +7,34 @@ namespace DS.WMS.Core.TaskInteraction.Dtos
/// </summary>
public class TaskStepDto
{
///// <summary>
///// ID
///// </summary>
//public long Id { get; set; }
/// <summary>
/// 步骤类型
/// </summary>
[SugarColumn(ColumnDescription = "明细类型")]
public StepType Type { get; set; }
/// <summary>
/// 名称
/// </summary>
[SugarColumn(ColumnDescription = "名称", Length = 50, IsNullable = true)]
public string? Name { get; set; }
/// <summary>
/// 值
/// </summary>
[SugarColumn(ColumnDescription = "值", IsNullable = true)]
public object? Value { get; set; }
/// <summary>
/// 是否已完成
/// </summary>
[SugarColumn(ColumnDescription = "是否已完成")]
public bool IsCompleted { get; set; }
/// <summary>
/// 优先级
/// </summary>
public int? Priority { get; set; }
}
}

@ -113,5 +113,11 @@ namespace DS.WMS.Core.TaskInteraction.Entity
/// </summary>
[Navigate(NavigateType.OneToMany, nameof(TaskStep.TaskId))]
public List<TaskStep>? Steps { get; set; }
/// <summary>
/// 任务步骤
/// </summary>
[Navigate(NavigateType.OneToMany, nameof(ParentId))]
public List<BusinessTask>? SubTasks { get; set; }
}
}

@ -2,6 +2,7 @@
using DS.WMS.Core.Flow.Dtos;
using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.TaskInteraction.Dtos;
using DS.WMS.Core.TaskInteraction.Entity;
namespace DS.WMS.Core.TaskInteraction.Interface
{
@ -21,9 +22,10 @@ namespace DS.WMS.Core.TaskInteraction.Interface
/// </summary>
/// <param name="id">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="withSubTask">是否获取子任务</param>
/// <param name="types">任务类型</param>
/// <returns></returns>
Task<DataResult<List<BusinessTaskDto>>> GetTasks(long id, BusinessType? businessType, params TaskBaseTypeEnum[] types);
Task<DataResult<List<BusinessTask>>> GetTasks(long id, BusinessType? businessType, bool withSubTask, params TaskBaseTypeEnum[] types);
/// <summary>
/// 返回指定类型的任务是否已存在

@ -35,11 +35,6 @@ namespace DS.WMS.Core.TaskInteraction.Method.ActionExecutor.BLConfirm
/// <returns></returns>
public async Task ExecuteAsync(ActionExecutionContext context)
{
//if (await taskService)
//{
//}
var bills = await TenantDb.Queryable<SeaExportBillManage>().Where(x => x.BusinessId == context.TaskInfo.BusinessId)
.Select(x => new
{
@ -68,7 +63,7 @@ namespace DS.WMS.Core.TaskInteraction.Method.ActionExecutor.BLConfirm
BusinessId = bill.Id,
BusinessType = context.TaskInfo.BusinessType,
TaskTypeName = TaskBaseTypeEnum.WAIT_SUB_BILL_CONFIRM.ToString(),
TaskTitle = $"{bill.BillType} {bill.HBLNO} {bill.ETD} {bill.Vessel}|{bill.Voyno}",
TaskTitle = $"【{TaskBaseTypeEnum.WAIT_SUB_BILL_CONFIRM.GetDescription()}】{bill.BillType} {bill.HBLNO} {bill.ETD?.ToString("yyyy-MM-dd")} {bill.Vessel}|{bill.Voyno}",
Steps = []
};

@ -22,7 +22,6 @@ using DS.WMS.Core.TaskPlat.Interface;
using Mapster;
using Masuit.Tools;
using Masuit.Tools.Systems;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
@ -123,8 +122,6 @@ namespace DS.WMS.Core.TaskInteraction.Method
/// </summary>
protected Lazy<IRuleEngineService> RuleEngineService { get; private set; }
readonly IConfiguration configuration;
/// <summary>
/// 初始化
/// </summary>
@ -135,7 +132,6 @@ namespace DS.WMS.Core.TaskInteraction.Method
LogService = provider.GetRequiredService<ITaskLogService>();
TaskAllocationService = provider.GetRequiredService<ITaskAllocationService>();
ActionService = provider.GetRequiredService<IActionManagerService>();
configuration = provider.GetRequiredService<IConfiguration>();
ClientParamService = new Lazy<IClientParamService>(provider.GetRequiredService<IClientParamService>());
FlowService = new Lazy<IClientFlowInstanceService>(provider.GetRequiredService<IClientFlowInstanceService>());
@ -185,23 +181,31 @@ namespace DS.WMS.Core.TaskInteraction.Method
/// <returns></returns>
public async Task<DataResult> CreateTaskAsync(TaskCreationRequest request, bool useTransaction = true)
{
if (request.BusinessType.HasValue)
if (!await HasAuthorizedAsync())
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ModuleUnauthorized));
if (request.Steps?.Count > 0)
{
bool isBizValid = false;
switch (request.BusinessType.Value)
{
case BusinessType.OceanShippingExport:
isBizValid = await TenantDb.Queryable<SeaExport>().AnyAsync(x => x.Id == request.BusinessId);
break;
}
if (request.Steps.Where(x => x.Type != StepType.NotSpecified).GroupBy(x => x.Type).Select(x => x.Key).Count() == 1)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.DuplicateStepType));
if (!isBizValid)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Biz_Not_Valid));
if (request.Steps.Any(x => x.Type == StepType.NotSpecified && string.IsNullOrEmpty(x.Name)))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TypeOrName));
}
//if (request.BusinessType.HasValue)
//{
// bool isBizValid = false;
// switch (request.BusinessType.Value)
// {
// case BusinessType.OceanShippingExport:
// isBizValid = await TenantDb.Queryable<SeaExport>().AnyAsync(x => x.Id == request.BusinessId);
// break;
// }
if (!await HasAuthorizedAsync())
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ModuleUnauthorized));
// if (!isBizValid)
// return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Biz_Not_Valid));
//}
if (request.HasCabin.GetValueOrDefault() && request.BusinessType.HasValue)
{
@ -254,8 +258,6 @@ namespace DS.WMS.Core.TaskInteraction.Method
TaskManageOrderMessageInfo? info = null;
if (task == null)
{
long tenatId = long.Parse(User.TenantId);
string tenatName = Db.Queryable<SysTenant>().Where(x => x.Id == tenatId).Select(x => x.Name).First();
info = new TaskManageOrderMessageInfo
{
Head = new TaskManageOrderMessageHeadInfo
@ -279,8 +281,8 @@ namespace DS.WMS.Core.TaskInteraction.Method
TaskDesp = request.TaskDescription,
TaskUserId = User.UserId,
TaskUserName = User.UserName,
TaskTenatId = tenatId,
TaskTenatName = tenatName,
TaskTenatId = long.Parse(User.TenantId),
TaskTenatName = User.TenantName,
IsCheckExistsByTaskType = true
}
};
@ -375,16 +377,13 @@ namespace DS.WMS.Core.TaskInteraction.Method
await TenantDb.Insertable(task).ExecuteCommandAsync();
if (request.Steps?.Count > 0)
{
if (request.Steps.Where(x => x.Type != StepType.NotSpecified).GroupBy(x => x.Type).Select(x => x.Key).Count() > 1)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.DuplicateStepType));
var steps = request.Steps.Select(x => new TaskStep
{
TaskId = task.Id,
IsCompleted = x.IsCompleted,
Name = x.Name,
Type = x.Type,
SortOrder = request.Steps.IndexOf(x),
SortOrder = x.Priority ?? request.Steps.IndexOf(x),
CreateBy = userId,
CreateTime = dtNow
}).ToList();
@ -564,6 +563,8 @@ namespace DS.WMS.Core.TaskInteraction.Method
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskNotExists));
if (task.TaskStatus == TaskStatusEnum.Complete)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskCompleted));
if (request.TaskStatus == TaskStatusEnum.Complete && await TenantDb.Queryable<BusinessTask>().AnyAsync(x => x.ParentId == task.Id && x.TaskStatus != request.TaskStatus))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.UnfinishedItems));
//检查是否有未完成的任务步骤
var steps = await TenantDb.Queryable<TaskStep>().Where(x => x.TaskId == task.Id && !x.IsCompleted)
@ -669,29 +670,39 @@ namespace DS.WMS.Core.TaskInteraction.Method
if (task.TaskStatus == TaskStatusEnum.Complete)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskCompleted));
var stepTypes = request.Steps.Select(x => x.Type);
var steps = await TenantDb.Queryable<TaskStep>().Where(x => x.TaskId == task.Id && stepTypes.Contains(x.Type))
var allSteps = await TenantDb.Queryable<TaskStep>().Where(x => x.TaskId == task.Id).OrderBy(x => x.SortOrder)
.Select(x => new TaskStep
{
Id = x.Id,
Type = x.Type,
Name = x.Name,
IsCompleted = x.IsCompleted,
SortOrder = x.SortOrder
}).ToListAsync();
//获取未完成的优先级最高的步骤
var topSteps = allSteps.Where(x => !x.IsCompleted).GroupBy(x => x.SortOrder).OrderBy(x => x.Key).FirstOrDefault();
var stepTypes = request.Steps.Select(x => x.Type);
List<TaskStep> steps = [];
long userId = long.Parse(User.UserId);
DateTime dtNow = DateTime.Now;
foreach (var item in steps)
foreach (var item in allSteps)
{
var reqStep = request.Steps.Find(x => x.Type == item.Type);
var reqStep = request.Steps.Find(x => x.Type == item.Type || (x.Type == StepType.NotSpecified && x.Name == item.Name));
if (reqStep == null)
continue;
if (topSteps.Any(x => x.SortOrder > item.SortOrder))
return DataResult.Failed(
MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.HigherUnfinishedItems)) + "" + string.Join("|", topSteps.Select(x => x.Type == StepType.NotSpecified ? x.Name : x.Type.GetDescription())),
nameof(MultiLanguageConst.HigherUnfinishedItems));
item.SetValue(reqStep.Value);
item.IsCompleted = reqStep.IsCompleted;
item.UpdateBy = userId;
item.UpdateTime = dtNow;
steps.Add(item);
}
await TenantDb.Updateable(steps).UpdateColumns(x => new
@ -704,12 +715,6 @@ namespace DS.WMS.Core.TaskInteraction.Method
if (request.AutoSync)
{
var allSteps = await TenantDb.Queryable<TaskStep>().Where(x => x.TaskId == task.Id)
.Select(x => new
{
x.Id,
x.IsCompleted
}).ToListAsync();
if (allSteps.Count > 0 && allSteps.Count == allSteps.Count(x => x.IsCompleted))
{
var result = await SetTaskStatusAsync(new TaskUpdateRequest
@ -751,20 +756,31 @@ namespace DS.WMS.Core.TaskInteraction.Method
}
/// <summary>
/// 获取业务的任务信息
/// 获取任务信息
/// </summary>
/// <param name="bsId">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="withSubTask">是否获取子任务</param>
/// <param name="types">任务类型</param>
/// <returns></returns>
public async Task<DataResult<List<BusinessTaskDto>>> GetTasks(long bsId, BusinessType? businessType, params TaskBaseTypeEnum[] types)
public async Task<DataResult<List<BusinessTask>>> GetTasks(long bsId, BusinessType? businessType, bool withSubTask, params TaskBaseTypeEnum[] types)
{
var list = await TenantDb.Queryable<BusinessTask>().Where(x => x.BusinessId == bsId)
var list = await TenantDb.Queryable<BusinessTask>().Includes(x => x.Steps).Where(x => x.BusinessId == bsId)
.WhereIF(businessType.HasValue, x => x.BusinessType == businessType)
.WhereIF(types != null && types.Length > 0, x => types.Contains(x.TaskType))
.Select<BusinessTaskDto>().ToListAsync();
.ToListAsync();
if (list.Count > 0 && withSubTask)
{
var ids = list.Select(x => x.Id);
var list2 = await TenantDb.Queryable<BusinessTask>().Includes(x => x.Steps)
.Where(x => x.ParentId.HasValue && ids.Contains(x.ParentId.Value)).ToListAsync();
foreach (var item in list)
item.SubTasks = list2.FindAll(x => x.ParentId == item.Id);
}
var result = DataResult<List<BusinessTaskDto>>.Success(list);
var result = DataResult<List<BusinessTask>>.Success(list);
result.Count = list.Count;
return result;
}

@ -5,8 +5,9 @@ using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.TaskInteraction.Dtos;
using DS.WMS.Core.TaskInteraction.Entity;
using DS.WMS.Core.TaskInteraction.Interface;
using Mapster;
using Masuit.Tools.Dynamics;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
namespace DS.WMS.OpApi.Controllers
{
@ -31,18 +32,20 @@ namespace DS.WMS.OpApi.Controllers
/// </summary>
/// <param name="businessId">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="withSubTask">是否获取子任务,默认为否</param>
/// <param name="taskTypes">任务类型名称(支持多个,可选参数)</param>
/// <returns></returns>
/// <remarks>/GetTasks?taskTypes=任务类型1&amp;taskTypes=任务类型2</remarks>
[HttpGet, Route("GetTasks")]
public async Task<DataResult<List<BusinessTaskDto>>> GetTasksAsync(
[FromQuery] long businessId, [FromQuery] BusinessType businessType, [FromQuery] params string[] taskTypes)
[HttpGet, HttpPost, Route("GetTasks")]
public async Task<DataResult<List<BusinessTask>>> GetTasksAsync(
long businessId, BusinessType businessType, bool withSubTask = false,
params string[] taskTypes)
{
TaskBaseTypeEnum[]? types = null;
if (taskTypes?.Length > 0)
types = taskTypes.Select(Enum.Parse<TaskBaseTypeEnum>).ToArray();
return await taskService.GetTasks(businessId, businessType, types);
return await taskService.GetTasks(businessId, businessType, withSubTask, types);
}
/// <summary>
@ -82,16 +85,24 @@ namespace DS.WMS.OpApi.Controllers
[HttpPost, Route("RunTaskAction")]
public async Task<DataResult> RunTaskActionAsync([FromServices] IActionManagerService actionService, [FromBody] TaskRequest request)
{
var result = await taskService.GetTasks(request.BusinessId, request.BusinessType, request.TaskType);
var result = await taskService.GetTasks(request.BusinessId, request.BusinessType, false, request.TaskType);
if (result.Data?.Count > 0)
{
var task = result.Data[0].Adapt<BusinessTask>();
var task = result.Data[0];
task.BusinessId = request.BusinessId;
task.BusinessType = request.BusinessType;
return await actionService.TriggerActionAsync(task, false);
Dictionary<string, object>? dic = null;
if (request.ExtraData is JObject jobject)
{
dic = [];
foreach (var item in jobject)
dic.Add(item.Key, item.Value?.ToString());
}
return await actionService.TriggerActionAsync(task, false,
request.ExtraData == null ? null : dic);
}
return DataResult.FailedWithDesc(MultiLanguageConst.EmptyData);
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
}
/// <summary>
@ -170,7 +181,7 @@ namespace DS.WMS.OpApi.Controllers
/// <param name="request"></param>
/// <returns></returns>
[HttpPost, Route("SetSteps")]
public async Task<DataResult> SetStepsAsync(TaskRequest request)
public async Task<DataResult> SetStepsAsync(TaskRequest request)
{
if (!ModelState.IsValid)
return DataResult.Failed(ModelState.GetErrorMessage(), MultiLanguageConst.IllegalRequest);

Loading…
Cancel
Save