You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

534 lines
21 KiB
C#

using System.Text;
using DS.Module.Core;
using DS.Module.Core.Data;
using DS.Module.Core.Extensions;
using DS.WMS.Core.Fee.Dtos;
using DS.WMS.Core.Flow.Dtos;
using DS.WMS.Core.Flow.Entity;
using DS.WMS.Core.Flow.Interface;
using DS.WMS.Core.Info.Dtos;
using DS.WMS.Core.Info.Entity;
using DS.WMS.Core.Info.Interface;
using DS.WMS.Core.Sys.Entity;
using DS.WMS.Core.TaskInteraction.Dtos;
using DS.WMS.Core.TaskInteraction.Interface;
using Masuit.Tools.Systems;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
namespace DS.WMS.Core.Info.Method
{
/// <summary>
/// 往来单位干系人
/// </summary>
public class ClientStakeholderService : ServiceBase, IClientStakeholderService
{
const TaskBaseTypeEnum CLIENT_STAKEHOLDER_TASK = TaskBaseTypeEnum.CLIENT_STAKEHOLDER_AUDIT;
const TaskBaseTypeEnum CLIENT_STAKEHOLDER_TASK_DISPUTE = TaskBaseTypeEnum.CLIENT_STAKEHOLDER_DISPUTE;
Lazy<IClientFlowInstanceService> flowService;
Lazy<IAuditTaskService> taskService;
/// <summary>
/// 初始化
/// </summary>
/// <param name="serviceProvider"></param>
public ClientStakeholderService(IServiceProvider serviceProvider) : base(serviceProvider)
{
flowService = new Lazy<IClientFlowInstanceService>(serviceProvider.GetRequiredService<IClientFlowInstanceService>());
taskService = new Lazy<IAuditTaskService>(serviceProvider.GetRequiredService<IAuditTaskService>());
}
#region 审核
/// <summary>
/// 提交审核
/// </summary>
/// <param name="idModel"></param>
/// <returns></returns>
public async Task<DataResult> SubmitAuditAsync(IdModel idModel)
{
//long.TryParse(idModel.Id, out long clientId);
//var list = await TenantDb.Queryable<InfoClientStakeholder>()
// .InnerJoin<InfoClient>((x, y) => x.ClientId == y.Id)
// .WhereIF(idModel.Ids?.Length > 0, (x, y) => idModel.Ids.Contains(x.Id))
// .WhereIF(clientId > 0, (x, y) => x.ClientId == clientId && x.Status == StakeholderStatus.Uncommitted)
// .Select((x, y) => new InfoClientStakeholder
// {
// ClientId = x.ClientId,
// Status = x.Status,
// UserName = x.UserName,
// ClientShortName = y.ShortName
// }).ToListAsync();
var list = await TenantDb.Queryable<InfoClientStakeholder>()
.InnerJoin<InfoClient>((x, y) => x.ClientId == y.Id)
.Where((x, y) => idModel.Ids.Contains(x.Id))
.Select((x, y) => new InfoClientStakeholder
{
ClientId = x.ClientId,
Status = x.Status,
UserName = x.UserName,
ClientShortName = y.ShortName
}).ToListAsync();
if (list.Count == 0)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.NoAuditItems));
if (list.Exists(x => x.Status == StakeholderStatus.Pending))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ItemsAreAuditing));
//var groups = list.GroupBy(x => new { x.ClientId, x.ClientShortName }).ToList();
var taskType = CLIENT_STAKEHOLDER_TASK;
if (idModel.Value is TaskBaseTypeEnum auditType)
taskType = auditType;
if (await taskService.Value.HasAuthorizedAsync())
{
var requests = list.Select(x => new TaskCreationRequest
{
BusinessId = x.Id,
TaskTypeName = taskType.ToString(),
TaskTitle = $"【{taskType.GetDescription()}】{x.ClientShortName} {x.UserName}"
});
//var requests = groups.Select(x => new TaskCreationRequest
//{
// BusinessId = x.Key.ClientId,
// TaskTypeName = taskType.ToString(),
// TaskTitle = $"【{taskType.GetDescription()}】{x.Key.ClientShortName} {string.Join("|", x.Select(y => y.UserName))}"
//});
await TenantDb.Ado.BeginTranAsync();
try
{
DataResult result;
foreach (var request in requests)
{
result = await taskService.Value.CreateTaskAsync(request, false);
if (!result.Succeeded)
return result;
}
await TenantDb.Updateable<InfoClientStakeholder>().Where(x => idModel.Ids.Contains(x.Id))
.SetColumns(x => x.Status == StakeholderStatus.Pending).ExecuteCommandAsync();
await TenantDb.Ado.CommitTranAsync();
return DataResult.Success;
}
catch (Exception ex)
{
await TenantDb.Ado.RollbackTranAsync();
await ex.LogAsync(Db);
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
}
var template = await FindTemplateAsync(taskType);
if (template == null)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TemplateNotFound));
//foreach (var g in groups)
//{
// var result = flowService.Value.CreateFlowInstance(new CreateFlowInstanceReq
// {
// BusinessId = g.Key.ClientId,
// TemplateId = template.Id
// });
// if (!result.Succeeded || result.Data is not FlowInstance instance)
// return result;
// result = flowService.Value.StartFlowInstance(instance.Id.ToString());
// if (!result.Succeeded)
// return result;
//}
foreach (var item in list)
{
var result = await flowService.Value.CreateAsync(new CreateFlowInstanceReq
{
BusinessId = item.Id,
TemplateId = template.Id
});
if (!result.Succeeded || result.Data is not FlowInstance instance)
return result;
result = await flowService.Value.StartAsync(instance.Id);
if (!result.Succeeded)
return result;
}
var ids = list.Select(x => x.Id);
var rows = await TenantDb.Updateable<InfoClientStakeholder>().Where(x => ids.Contains(x.Id))
.SetColumns(x => x.Status == StakeholderStatus.Pending).ExecuteCommandAsync();
return rows > 0 ? DataResult.Success : DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
/// <summary>
/// 执行审核
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<DataResult> AuditAsync(AuditRequest request)
{
if (await taskService.Value.HasAuthorizedAsync())
{
return await taskService.Value.AuditAsync(new TaskAuditRequest
{
Ids = request.Ids,
Remark = request.Remark,
Result = request.Result,
TaskTypeName = CLIENT_STAKEHOLDER_TASK.ToString()
});
}
var list = await flowService.Value.GetInstancesAsync(CLIENT_STAKEHOLDER_TASK, ids: request.Ids);
if (list.Count != request.Ids.Length)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.NotInAudit));
foreach (var item in list)
{
var result = await flowService.Value.AuditAsync(new FlowAuditInfo
{
AuditNote = request.Remark,
Status = request.Result,
Instance = item
});
if (!result.Succeeded)
return result;
}
return DataResult.Success;
}
/// <summary>
/// 撤销审核
/// </summary>
/// <param name="idModel"></param>
/// <returns></returns>
public async Task<DataResult> WithdrawAsync(IdModel idModel)
{
DataResult result;
if (await taskService.Value.HasAuthorizedAsync())
{
await TenantDb.Ado.BeginTranAsync();
try
{
for (int i = 0; i < idModel.Ids.Length; i++)
{
result = await taskService.Value.WithdrawAsync(new TaskRequest
{
BusinessId = idModel.Ids[i],
TaskTypeName = CLIENT_STAKEHOLDER_TASK.ToString()
}, false);
if (!result.Succeeded)
{
return result;
}
}
await TenantDb.Updateable<InfoClientStakeholder>().Where(x => idModel.Ids.Contains(x.Id))
.SetColumns(x => x.Status == StakeholderStatus.Uncommitted)
.SetColumns(x => x.Remark == null)
.ExecuteCommandAsync();
await TenantDb.Ado.CommitTranAsync();
return DataResult.Success;
}
catch
{
await TenantDb.Ado.RollbackTranAsync();
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
}
var list = await flowService.Value.GetInstancesAsync(CLIENT_STAKEHOLDER_TASK, ids: idModel.Ids);
if (list.Count != idModel.Ids.Length)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.NotInAudit));
result = await flowService.Value.WithdrawAsync(idModel.Ids);
if (!result.Succeeded)
return result;
int rows = await TenantDb.Updateable<InfoClientStakeholder>().Where(x => idModel.Ids.Contains(x.Id))
.SetColumns(x => x.Status == StakeholderStatus.Uncommitted).ExecuteCommandAsync();
return rows > 0 ? DataResult.Success : DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
/// <summary>
/// 审核完成回调
/// </summary>
/// <param name="callback">回调信息</param>
/// <returns></returns>
public async Task<DataResult> AuditCallbackAsync(FlowCallback callback)
{
if (callback.AuditType != CLIENT_STAKEHOLDER_TASK || callback.AuditType != CLIENT_STAKEHOLDER_TASK_DISPUTE)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.AuditUnauthorization));
//var list = await TenantDb.Queryable<InfoClientStakeholder>().Where(x => x.ClientId == callback.BusinessId)
// .Select(x => new InfoClientStakeholder
// {
// Id = callback.BusinessId,
// Remark = callback.RejectReason
// }).ToListAsync();
var list = await TenantDb.Queryable<InfoClientStakeholder>().Where(x => x.Id == callback.BusinessId)
.Select(x => new InfoClientStakeholder
{
Id = callback.BusinessId,
Remark = callback.RejectReason
}).ToListAsync();
foreach (var item in list)
{
item.Status = callback.FlowStatus == FlowStatusEnum.Approve ? StakeholderStatus.Approved : StakeholderStatus.Rejected;
}
await TenantDb.Ado.BeginTranAsync();
try
{
int rows = await TenantDb.Updateable(list).UpdateColumns(x => new
{
x.Remark,
x.Status
}).ExecuteCommandAsync();
////如果状态为驳回则发起争议审核
//if (callback.FlowStatus == FlowStatusEnum.Reject && callback.AuditType == CLIENT_STAKEHOLDER_TASK)
//{
// var result = await SubmitAuditAsync(new IdModel
// {
// Id = callback.BusinessId.ToString(),
// Value = CLIENT_STAKEHOLDER_TASK_DISPUTE
// });
// if (!result.Succeeded)
// return result;
//}
await TenantDb.Ado.CommitTranAsync();
return DataResult.Success;
}
catch (Exception ex)
{
await TenantDb.Ado.RollbackTranAsync();
await ex.LogAsync(Db);
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
}
#endregion
/// <summary>
/// 导入
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
public async Task<DataResult> ImportAsync(List<InfoClientStakeholderModel> list)
{
var clientNames = list.Select(x => x.CustomerName).Distinct();
var clients = await TenantDb.Queryable<InfoClient>().Where(x => clientNames.Contains(x.ShortName) || clientNames.Contains(x.Description))
.Select(x => new
{
x.Id,
x.ShortName,
x.Description,
x.OrgId
}).ToListAsync();
var userCodes = list.Select(x => x.StakeholderName).Distinct();
var users = await Db.Queryable<SysUser>().Where(x => userCodes.Contains(x.UserName)).Select(x => new
{
x.Id,
x.UserName,
x.UserCode
}).ToListAsync();
StringBuilder sb = new();
List<InfoClientStakeholder> stakeholders = new(list.Count);
long userId = long.Parse(User.UserId);
DateTime dtNow = DateTime.Now.Date;
foreach (var model in list)
{
if (dtNow > model.EndDate)
continue;
var client = clients.Find(x => x.ShortName == model.CustomerName || x.Description == model.CustomerName);
if (client == null)
{
sb.Append("," + model.CustomerName);
continue;
}
var user = users.Find(x => x.UserName == model.StakeholderName);
if (user == null)
{
sb.Append("," + model.StakeholderName);
continue;
}
InfoClientStakeholder stakeholder = new()
{
ClientId = client.Id,
UserId = user.Id,
UserName = model.StakeholderName,
StartDate = model.StartDate,
EndDate = model.EndDate,
Status = StakeholderStatus.Approved,
Remark = "系统导入",
CreateBy = userId,
CreateByName = User.UserName,
CreateTime = dtNow
};
stakeholders.Add(stakeholder);
}
//if (sb.Length > 0)
//{
// sb.Remove(0, 1);
// return DataResult.Failed("下列数据匹配不到客户/供应商或干系人信息:" + sb.ToString());
//}
await TenantDb.Ado.BeginTranAsync();
try
{
await TenantDb.Fastest<InfoClientStakeholder>().BulkCopyAsync(stakeholders);
await TenantDb.Ado.CommitTranAsync();
return DataResult.Success;
}
catch (Exception ex)
{
await TenantDb.Ado.RollbackTranAsync();
await ex.LogAsync(Db);
return DataResult.Failed("导入失败:" + ex.Message);
}
}
/// <summary>
/// 列表
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<DataResult<List<InfoClientStakeholder>>> GetListAsync(PageRequest request)
{
//序列化查询条件
var whereList = request.GetConditionalModels(Db);
var result = await TenantDb.Queryable<InfoClientStakeholder>()
.Where(whereList)
.ToQueryPageAsync(request.PageCondition);
if (result.Data?.Count > 0)
{
var ids = result.Data.Select(x => x.ClientId).Distinct();
var clients = await TenantDb.Queryable<InfoClient>().Where(x => ids.Contains(x.Id))
.Select(x => new
{
x.Id,
x.ShortName
}).ToListAsync();
foreach (var item in result.Data)
{
item.ClientShortName = clients.Find(x => x.Id == item.ClientId)?.ShortName;
}
}
return result;
}
/// <summary>
/// 获取客户干系人
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<DataResult<InfoClientStakeholder>> GetAsync(long id)
{
var model = await TenantDb.Queryable<InfoClientStakeholder>().FirstAsync(x => x.Id == id);
return DataResult<InfoClientStakeholder>.Success(model);
}
/// <summary>
/// 创建/更新客户干系人
/// </summary>
/// <param name="stakeholders">干系人</param>
/// <returns></returns>
public async Task<DataResult> EditAsync(params InfoClientStakeholder[] stakeholders)
{
var result = await IsAvailableAsync(stakeholders);
if (!result.Succeeded)
return result;
var userId = long.Parse(User.UserId);
var dtNow = DateTime.Now;
for (var i = 0; i < stakeholders.Length; i++)
{
var item = stakeholders[i];
item.CreateBy = userId;
item.CreateByName = User.UserName;
item.CreateTime = dtNow;
}
await TenantDb.Storageable(stakeholders).DefaultAddElseUpdate().ExecuteCommandAsync();
result = DataResult.Success;
result.Data = stakeholders;
return result;
}
/// <summary>
/// 创建客户干系人并提交审核
/// </summary>
/// <param name="stakeholder">干系人</param>
/// <returns></returns>
public async Task<DataResult> AddSubmitAsync(InfoClientStakeholder stakeholder)
{
var result = await IsAvailableAsync(stakeholder);
if (!result.Succeeded)
return result;
stakeholder.CreateBy = long.Parse(User.UserId);
stakeholder.CreateByName = User.UserName;
stakeholder.CreateTime = DateTime.Now;
await TenantDb.Insertable(stakeholder).ExecuteCommandAsync();
return await SubmitAuditAsync(new IdModel { Id = stakeholder.Id.ToString(), Ids = [stakeholder.Id] });
}
/// <summary>
/// 检查干系人是否存在
/// </summary>
/// <param name="stakeholders">干系人</param>
/// <returns></returns>
public async Task<DataResult> IsAvailableAsync(params InfoClientStakeholder[] stakeholders)
{
var dtNow = DateTime.Now.Date;
var clientId = stakeholders[0].ClientId;
var ids1 = stakeholders.Select(x => x.UserId);
var ids2 = stakeholders.Where(x => x.Id > 0).Select(x => x.Id);
var expr = Expressionable.Create<InfoClientStakeholder>()
.And(x => x.ClientId == clientId && ids1.Contains(x.UserId) && SqlFunc.Between(dtNow, x.StartDate, x.EndDate))
.AndIF(ids2.Any(), x => !ids2.Contains(x.Id));
if (await TenantDb.Queryable<InfoClientStakeholder>().AnyAsync(expr.ToExpression()))
{
var result = DataResult.FailedWithDesc(nameof(MultiLanguageConst.StakeholderExist));
result.Code = ResultCode.Fail;
result.Data = stakeholders;
return result;
}
return DataResult.Success;
}
/// <summary>
/// 删除干系人
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
public async Task<DataResult> DeleteAsync(params long[] ids)
{
await TenantDb.Deleteable<InfoClientStakeholder>()
.Where(x => ids.Contains(x.Id)).ExecuteCommandAsync();
return DataResult.Success;
}
}
}