|
|
|
@ -1,6 +1,10 @@
|
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
using System.Net.Mail;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using Autofac.Core;
|
|
|
|
|
using Castle.Core.Resource;
|
|
|
|
|
using DS.Module.Core;
|
|
|
|
|
using DS.Module.Core.Condition;
|
|
|
|
|
using DS.Module.Core.Data;
|
|
|
|
|
using DS.Module.Core.Extensions;
|
|
|
|
|
using DS.Module.PrintModule;
|
|
|
|
@ -14,8 +18,10 @@ using DS.WMS.Core.TaskInteraction.Entity;
|
|
|
|
|
using DS.WMS.Core.TaskInteraction.Interface;
|
|
|
|
|
using Fasterflect;
|
|
|
|
|
using HtmlAgilityPack;
|
|
|
|
|
using LanguageExt.Pretty;
|
|
|
|
|
using Masuit.Tools;
|
|
|
|
|
using Masuit.Tools.Systems;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
|
using Microsoft.Extensions.Configuration;
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
@ -51,6 +57,7 @@ namespace DS.WMS.Core.TaskInteraction.Method
|
|
|
|
|
|
|
|
|
|
readonly IConfiguration config;
|
|
|
|
|
readonly ILogger<MailTemplateService> logger;
|
|
|
|
|
readonly Lazy<IActionManagerService> actionService;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 初始化
|
|
|
|
@ -60,6 +67,7 @@ namespace DS.WMS.Core.TaskInteraction.Method
|
|
|
|
|
{
|
|
|
|
|
config = provider.GetRequiredService<IConfiguration>();
|
|
|
|
|
logger = provider.GetRequiredService<ILogger<MailTemplateService>>();
|
|
|
|
|
actionService = new Lazy<IActionManagerService>(provider.GetRequiredService<IActionManagerService>());
|
|
|
|
|
|
|
|
|
|
Db.QueryFilter.Clear<ITenantId>();
|
|
|
|
|
TenantDb.QueryFilter.Clear<IOrgId>();
|
|
|
|
@ -252,6 +260,91 @@ namespace DS.WMS.Core.TaskInteraction.Method
|
|
|
|
|
{
|
|
|
|
|
var actionManager = ServiceProvider.GetRequiredService<IActionManagerService>();
|
|
|
|
|
model.Primary = await actionManager.GetBusinessDataAsync(bsId, bsType.GetValueOrDefault());
|
|
|
|
|
|
|
|
|
|
var custQuery = TenantDb.UnionAll(
|
|
|
|
|
TenantDb.Queryable<InfoClient>().Where(c => SqlFunc.Subqueryable<SeaExport>().Where(s => s.CustomerId == c.Id && s.Id == bsId).Any())
|
|
|
|
|
.Select(c => new InfoClient { Description = c.Description, Note = "controller" }),
|
|
|
|
|
TenantDb.Queryable<InfoClient>().Where(c => SqlFunc.Subqueryable<SeaExport>().Where(s => s.ForwarderId == c.Id && s.Id == bsId).Any())
|
|
|
|
|
.Select(c => new InfoClient { Description = c.Description, Note = "booking" }),
|
|
|
|
|
TenantDb.Queryable<InfoClient>().Where(c => SqlFunc.Subqueryable<SeaExport>().Where(s => s.ShipperCnId == c.Id && s.Id == bsId).Any())
|
|
|
|
|
.Select(c => new InfoClient { Description = c.Description, Note = "shipperCN" })
|
|
|
|
|
);
|
|
|
|
|
var custList = await custQuery.ToListAsync();
|
|
|
|
|
model.CustomerName = custList.Find(x => x.Note == "controller")?.Description ?? string.Empty;
|
|
|
|
|
model.ForwarderName = custList.Find(x => x.Note == "booking")?.Description ?? string.Empty;
|
|
|
|
|
model.DomesticShipperName = custList.Find(x => x.Note == "shipperCN")?.Description ?? string.Empty;
|
|
|
|
|
|
|
|
|
|
var userQuery = TenantDb.UnionAll(
|
|
|
|
|
TenantDb.Queryable<SeaExport>().InnerJoin<SysUser>((s, u) => s.SaleId == u.Id, "shippingweb8_dev.sys_user")
|
|
|
|
|
.Where((s, u) => s.Id == bsId)
|
|
|
|
|
.Select((s, u) => new Contact
|
|
|
|
|
{
|
|
|
|
|
Code = u.UserCode,
|
|
|
|
|
Email = u.Email,
|
|
|
|
|
EnName = u.UserEnName,
|
|
|
|
|
Name = u.UserName,
|
|
|
|
|
Mobile = u.Phone,
|
|
|
|
|
Tel = u.OfficePhone,
|
|
|
|
|
QQ = u.QQ,
|
|
|
|
|
CustomerType = "s"
|
|
|
|
|
}),
|
|
|
|
|
TenantDb.Queryable<SeaExport>().InnerJoin<SysUser>((s, u) => s.SaleId == u.Id, "shippingweb8_dev.sys_user")
|
|
|
|
|
.Where((s, u) => s.Id == bsId)
|
|
|
|
|
.Select((s, u) => new Contact
|
|
|
|
|
{
|
|
|
|
|
Code = u.UserCode,
|
|
|
|
|
Email = u.Email,
|
|
|
|
|
EnName = u.UserEnName,
|
|
|
|
|
Name = u.UserName,
|
|
|
|
|
Mobile = u.Phone,
|
|
|
|
|
Tel = u.OfficePhone,
|
|
|
|
|
QQ = u.QQ,
|
|
|
|
|
CustomerType = "o"
|
|
|
|
|
}),
|
|
|
|
|
TenantDb.Queryable<SeaExport>().InnerJoin<SysUser>((s, u) => s.SaleId == u.Id, "shippingweb8_dev.sys_user")
|
|
|
|
|
.Where((s, u) => s.Id == bsId)
|
|
|
|
|
.Select((s, u) => new Contact
|
|
|
|
|
{
|
|
|
|
|
Code = u.UserCode,
|
|
|
|
|
Email = u.Email,
|
|
|
|
|
EnName = u.UserEnName,
|
|
|
|
|
Name = u.UserName,
|
|
|
|
|
Mobile = u.Phone,
|
|
|
|
|
Tel = u.OfficePhone,
|
|
|
|
|
QQ = u.QQ,
|
|
|
|
|
CustomerType = "c"
|
|
|
|
|
}),
|
|
|
|
|
TenantDb.Queryable<SeaExport>().InnerJoin<SysUser>((s, u) => s.SaleId == u.Id, "shippingweb8_dev.sys_user")
|
|
|
|
|
.Where((s, u) => s.Id == bsId)
|
|
|
|
|
.Select((s, u) => new Contact
|
|
|
|
|
{
|
|
|
|
|
Code = u.UserCode,
|
|
|
|
|
Email = u.Email,
|
|
|
|
|
EnName = u.UserEnName,
|
|
|
|
|
Name = u.UserName,
|
|
|
|
|
Mobile = u.Phone,
|
|
|
|
|
Tel = u.OfficePhone,
|
|
|
|
|
QQ = u.QQ,
|
|
|
|
|
CustomerType = "d"
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
var userList = await userQuery.ToListAsync();
|
|
|
|
|
model.Sales = userList.Find(x => x.CustomerType == "s");
|
|
|
|
|
model.Operator = userList.Find(x => x.CustomerType == "o");
|
|
|
|
|
model.CustomerService = userList.Find(x => x.CustomerType == "c");
|
|
|
|
|
model.Document = userList.Find(x => x.CustomerType == "d");
|
|
|
|
|
|
|
|
|
|
//获取箱型价格
|
|
|
|
|
model.CtnPriceList = await TenantDb.Queryable<BusinessCtnPrice>().Where(x => x.BusinessId == model.BusinessId)
|
|
|
|
|
.Select(x => new BusinessCtnPrice
|
|
|
|
|
{
|
|
|
|
|
Ctn = x.Ctn,
|
|
|
|
|
CtnAll = x.CtnAll,
|
|
|
|
|
CtnNum = x.CtnNum,
|
|
|
|
|
QuotePrice = x.QuotePrice,
|
|
|
|
|
GuidePrice = x.GuidePrice,
|
|
|
|
|
FloorPrice = x.FloorPrice
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@ -282,109 +375,6 @@ namespace DS.WMS.Core.TaskInteraction.Method
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (model.Primary == null)
|
|
|
|
|
return model;
|
|
|
|
|
|
|
|
|
|
List<Tuple<long, string>> list = [];
|
|
|
|
|
long? forwarderId = null, shipperCNId = null, customerId = null;
|
|
|
|
|
var order = model.Primary as SeaExportRes;
|
|
|
|
|
order ??= await TenantDb.Queryable<SeaExport>().Where(x => x.Id == bsId)
|
|
|
|
|
.Select(x => new SeaExportRes
|
|
|
|
|
{
|
|
|
|
|
SaleId = x.SaleId,
|
|
|
|
|
OperatorId = x.OperatorId,
|
|
|
|
|
CustomerService = x.CustomerService,
|
|
|
|
|
Doc = x.Doc,
|
|
|
|
|
ForwarderId = x.ForwarderId,
|
|
|
|
|
ShipperCnId = x.ShipperCnId,
|
|
|
|
|
CustomerId = x.CustomerId
|
|
|
|
|
}).FirstAsync();
|
|
|
|
|
|
|
|
|
|
if (order != null)
|
|
|
|
|
{
|
|
|
|
|
list.Add(new Tuple<long, string>(order.SaleId, "sale"));
|
|
|
|
|
list.Add(new Tuple<long, string>(order.OperatorId, "op"));
|
|
|
|
|
list.Add(new Tuple<long, string>(order.CustomerService, "cs"));
|
|
|
|
|
list.Add(new Tuple<long, string>(order.Doc, "doc"));
|
|
|
|
|
|
|
|
|
|
forwarderId = order.ForwarderId;
|
|
|
|
|
shipperCNId = order.ShipperCnId;
|
|
|
|
|
customerId = order.CustomerId;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (model.Primary is not IDictionary<string, object> dic)
|
|
|
|
|
return model;
|
|
|
|
|
|
|
|
|
|
if (dic.TryGetValue(nameof(SeaExport.SaleId), out object? sale))
|
|
|
|
|
list.Add(new Tuple<long, string>((long)sale, nameof(sale)));
|
|
|
|
|
|
|
|
|
|
if (dic.TryGetValue(nameof(SeaExport.OperatorId), out object? op))
|
|
|
|
|
list.Add(new Tuple<long, string>((long)op, nameof(op)));
|
|
|
|
|
|
|
|
|
|
if (dic.TryGetValue(nameof(SeaExport.CustomerService), out object? cs))
|
|
|
|
|
list.Add(new Tuple<long, string>((long)cs, nameof(cs)));
|
|
|
|
|
|
|
|
|
|
if (dic.TryGetValue(nameof(SeaExport.Doc), out object? doc))
|
|
|
|
|
list.Add(new Tuple<long, string>((long)doc, nameof(doc)));
|
|
|
|
|
|
|
|
|
|
if (dic.TryGetValue(nameof(SeaExport.ForwarderId), out object? forwarder) && forwarder != null)
|
|
|
|
|
forwarderId = (long)forwarder;
|
|
|
|
|
|
|
|
|
|
if (dic.TryGetValue(nameof(SeaExport.ShipperCnId), out object? shipperCN) && shipperCN != null)
|
|
|
|
|
shipperCNId = (long)shipperCN;
|
|
|
|
|
|
|
|
|
|
if (dic.TryGetValue(nameof(SeaExport.CustomerId), out object? customer) && customer != null)
|
|
|
|
|
customerId = (long)customer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
long?[] custIds = [forwarderId, shipperCNId, customerId];
|
|
|
|
|
var custList = await TenantDb.Queryable<InfoClient>().Where(x => custIds.Contains(x.Id))
|
|
|
|
|
.Select(x => new { x.Id, x.Description }).ToListAsync();
|
|
|
|
|
model.ForwarderName = custList.Find(x => x.Id == forwarderId)?.Description;
|
|
|
|
|
model.DomesticShipperName = custList.Find(x => x.Id == shipperCNId)?.Description;
|
|
|
|
|
model.CustomerName = custList.Find(x => x.Id == customerId)?.Description;
|
|
|
|
|
|
|
|
|
|
if (list.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
var ids = list.Select(x => x.Item1).ToArray();
|
|
|
|
|
var userList = await Db.Queryable<SysUser>().Where(x => ids.Contains(x.Id)).Select(x => new Contact
|
|
|
|
|
{
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
Code = x.UserCode,
|
|
|
|
|
Email = x.Email,
|
|
|
|
|
EnName = x.UserEnName,
|
|
|
|
|
Name = x.UserName,
|
|
|
|
|
Mobile = x.Phone,
|
|
|
|
|
Tel = x.OfficePhone,
|
|
|
|
|
QQ = x.QQ
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
long saleId = list.Find(x => x.Item2 == "sale")!.Item1;
|
|
|
|
|
model.Sales = userList.Find(x => x.Id == saleId);
|
|
|
|
|
|
|
|
|
|
long opId = list.Find(x => x.Item2 == "op")!.Item1;
|
|
|
|
|
model.Operator = userList.Find(x => x.Id == opId);
|
|
|
|
|
|
|
|
|
|
long csId = list.Find(x => x.Item2 == "cs")!.Item1;
|
|
|
|
|
model.CustomerService = userList.Find(x => x.Id == csId);
|
|
|
|
|
|
|
|
|
|
long docId = list.Find(x => x.Item2 == "doc")!.Item1;
|
|
|
|
|
model.Document = userList.Find(x => x.Id == docId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//获取箱型价格
|
|
|
|
|
model.CtnPriceList = await TenantDb.Queryable<BusinessCtnPrice>().Where(x => x.BusinessId == model.BusinessId)
|
|
|
|
|
.Select(x => new BusinessCtnPrice
|
|
|
|
|
{
|
|
|
|
|
Ctn = x.Ctn,
|
|
|
|
|
CtnAll = x.CtnAll,
|
|
|
|
|
CtnNum = x.CtnNum,
|
|
|
|
|
QuotePrice = x.QuotePrice,
|
|
|
|
|
GuidePrice = x.GuidePrice,
|
|
|
|
|
FloorPrice = x.FloorPrice
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
return model;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -545,6 +535,17 @@ namespace DS.WMS.Core.TaskInteraction.Method
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 使用邮件草稿发送邮件
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="draftId">邮件草稿ID</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult> SendAsync(long draftId)
|
|
|
|
|
{
|
|
|
|
|
var draft = await TenantDb.Queryable<MailDraft>().FirstAsync(x => x.Id == draftId);
|
|
|
|
|
return await SendAsync(draft);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 使用邮件草稿发送邮件
|
|
|
|
|
/// </summary>
|
|
|
|
@ -552,11 +553,26 @@ namespace DS.WMS.Core.TaskInteraction.Method
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult> SendAsync(MailDraft draft)
|
|
|
|
|
{
|
|
|
|
|
ArgumentNullException.ThrowIfNull(draft, nameof(draft));
|
|
|
|
|
if (draft == null)
|
|
|
|
|
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(draft.SendTo) || string.IsNullOrEmpty(draft.Account) || string.IsNullOrEmpty(draft.Password) || string.IsNullOrEmpty(draft.Server) || draft.Port <= 0)
|
|
|
|
|
return DataResult.Failed("邮件信息不完整,请补全(收件人/发件SMTP配置)后重试");
|
|
|
|
|
|
|
|
|
|
var mailResult = await Api.SendRequestAsync(HttpMethod.Post, config["TaskMail:MailApiUrl"], draft);
|
|
|
|
|
if (mailResult.IsSuccessStatusCode)
|
|
|
|
|
{
|
|
|
|
|
draft.HasSent = true;
|
|
|
|
|
draft.UpdateBy = UserId;
|
|
|
|
|
draft.UpdateTime = DateTime.Now;
|
|
|
|
|
await TenantDb.Updateable(draft).UpdateColumns(x => new
|
|
|
|
|
{
|
|
|
|
|
x.HasSent,
|
|
|
|
|
x.UpdateBy,
|
|
|
|
|
x.UpdateTime
|
|
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
return DataResult.Successed($"已发邮件,收件人:" + string.Join(",", draft.SendTo) + "发件人:" + draft.Account);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DataResult.Failed($"邮件发送失败,API返回状态为:{(int)mailResult.StatusCode} {mailResult.StatusCode}"
|
|
|
|
|
+ $"收件人:" + string.Join(",", draft.SendTo) + "发件人:" + draft.Account);
|
|
|
|
@ -589,8 +605,7 @@ namespace DS.WMS.Core.TaskInteraction.Method
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult<MailDraft>> CreateDraftAsync(BusinessTask task, MailTemplateModel? templateModel = null, bool saveDraft = false)
|
|
|
|
|
{
|
|
|
|
|
var mailConfig = await TenantDb.Queryable<BusinessTaskMail>()
|
|
|
|
|
.Includes(x => x.Sender).Includes(x => x.Receivers).Includes(x => x.CC).Includes(x => x.Attachments)
|
|
|
|
|
var mailConfig = await TenantDb.Queryable<BusinessTaskMail>().Includes(x => x.Attachments)
|
|
|
|
|
.Where(x => SqlFunc.Subqueryable<TaskMailRelation>().Where(y => x.Id == y.MailId && y.TaskType == task.TaskType && y.IsDefault).Any())
|
|
|
|
|
.FirstAsync();
|
|
|
|
|
if (mailConfig == null)
|
|
|
|
@ -614,77 +629,197 @@ namespace DS.WMS.Core.TaskInteraction.Method
|
|
|
|
|
ArgumentNullException.ThrowIfNull(task, nameof(task));
|
|
|
|
|
|
|
|
|
|
templateModel ??= await GetBusinessModelAsync(mailConfig, task.BusinessId, task.BusinessType);
|
|
|
|
|
var order = await TenantDb.Queryable<SeaExport>().Where(x => x.Id == templateModel.BusinessId)
|
|
|
|
|
.Select(x => new
|
|
|
|
|
{
|
|
|
|
|
x.CustomerNo,
|
|
|
|
|
x.SaleId,
|
|
|
|
|
x.OperatorId,
|
|
|
|
|
x.CustomerService,
|
|
|
|
|
x.Doc,
|
|
|
|
|
x.CarrierId,
|
|
|
|
|
x.ForwarderId,
|
|
|
|
|
x.YardId,
|
|
|
|
|
x.TruckerId,
|
|
|
|
|
x.CustomerId
|
|
|
|
|
}).FirstAsync();
|
|
|
|
|
if (order == null)
|
|
|
|
|
return DataResult<MailDraft>.Failed($"未能获取订单({templateModel.BusinessId})数据");
|
|
|
|
|
|
|
|
|
|
//设置发件人
|
|
|
|
|
if (mailConfig.Sender == null)
|
|
|
|
|
return DataResult<MailDraft>.Failed("未设置发件人");
|
|
|
|
|
|
|
|
|
|
long senderId = 0;
|
|
|
|
|
if (mailConfig.Sender.IsSale)
|
|
|
|
|
senderId = order.SaleId;
|
|
|
|
|
else if (mailConfig.Sender.IsOperator)
|
|
|
|
|
senderId = order.OperatorId;
|
|
|
|
|
else if (mailConfig.Sender.IsCustomerService)
|
|
|
|
|
senderId = order.CustomerService;
|
|
|
|
|
else if (mailConfig.Sender.IsVouchingClerk)
|
|
|
|
|
senderId = order.Doc;
|
|
|
|
|
|
|
|
|
|
templateModel.Sender = await Db.Queryable<SysUser>().Where(x => x.Id == senderId).Select(x => new MailSender
|
|
|
|
|
{
|
|
|
|
|
DisplayName = x.UserName,
|
|
|
|
|
Phone = x.Phone,
|
|
|
|
|
SignatureHtml = x.SignatureHtml
|
|
|
|
|
}).FirstAsync();
|
|
|
|
|
if (templateModel.Sender == null)
|
|
|
|
|
return DataResult<MailDraft>.Failed("邮件模板未设置发件人");
|
|
|
|
|
|
|
|
|
|
var senderConfig = await TenantDb.Queryable<CodeUserEmail>().FirstAsync(x => x.CreateBy == senderId);
|
|
|
|
|
var query = TenantDb.UnionAll(
|
|
|
|
|
//-----发送人-----//
|
|
|
|
|
TenantDb.Queryable<SeaExport>()
|
|
|
|
|
.InnerJoin<SysUser>((s, u) => s.SaleId == u.Id, "shippingweb8_dev.sys_user")
|
|
|
|
|
.Where((s, u) => s.Id == task.BusinessId && SqlFunc.Subqueryable<BusinessTaskMailSender>()
|
|
|
|
|
.Where(tms => tms.TaskMailId == mailConfig.Id && tms.IsSale).Any())
|
|
|
|
|
.LeftJoin<CodeUserEmail>((s, u, um) => u.Id == um.CreateBy)
|
|
|
|
|
.Select((s, u, um) => new
|
|
|
|
|
{
|
|
|
|
|
u.Id,
|
|
|
|
|
u.UserName,
|
|
|
|
|
u.Phone,
|
|
|
|
|
u.Email,
|
|
|
|
|
u.SignatureHtml,
|
|
|
|
|
um.ShowName,
|
|
|
|
|
um.MailAccount,
|
|
|
|
|
um.Password,
|
|
|
|
|
um.SmtpServer,
|
|
|
|
|
um.SmtpPort,
|
|
|
|
|
um.SmtpSSL,
|
|
|
|
|
UserType = "Sender"
|
|
|
|
|
}),
|
|
|
|
|
TenantDb.Queryable<SeaExport>()
|
|
|
|
|
.InnerJoin<SysUser>((s, u) => s.OperatorId == u.Id, "shippingweb8_dev.sys_user")
|
|
|
|
|
.Where((s, u) => s.Id == task.BusinessId && SqlFunc.Subqueryable<BusinessTaskMailSender>()
|
|
|
|
|
.Where(tms => tms.TaskMailId == mailConfig.Id && tms.IsOperator).Any())
|
|
|
|
|
.LeftJoin<CodeUserEmail>((s, u, um) => u.Id == um.CreateBy)
|
|
|
|
|
.Select((s, u, um) => new
|
|
|
|
|
{
|
|
|
|
|
u.Id,
|
|
|
|
|
u.UserName,
|
|
|
|
|
u.Phone,
|
|
|
|
|
u.Email,
|
|
|
|
|
u.SignatureHtml,
|
|
|
|
|
um.ShowName,
|
|
|
|
|
um.MailAccount,
|
|
|
|
|
um.Password,
|
|
|
|
|
um.SmtpServer,
|
|
|
|
|
um.SmtpPort,
|
|
|
|
|
um.SmtpSSL,
|
|
|
|
|
UserType = "Sender"
|
|
|
|
|
}),
|
|
|
|
|
TenantDb.Queryable<SeaExport>()
|
|
|
|
|
.InnerJoin<SysUser>((s, u) => s.CustomerService == u.Id, "shippingweb8_dev.sys_user")
|
|
|
|
|
.Where((s, u) => s.Id == task.BusinessId && SqlFunc.Subqueryable<BusinessTaskMailSender>()
|
|
|
|
|
.Where(tms => tms.TaskMailId == mailConfig.Id && tms.IsCustomerService).Any())
|
|
|
|
|
.LeftJoin<CodeUserEmail>((s, u, um) => u.Id == um.CreateBy)
|
|
|
|
|
.Select((s, u, um) => new
|
|
|
|
|
{
|
|
|
|
|
u.Id,
|
|
|
|
|
u.UserName,
|
|
|
|
|
u.Phone,
|
|
|
|
|
u.Email,
|
|
|
|
|
u.SignatureHtml,
|
|
|
|
|
um.ShowName,
|
|
|
|
|
um.MailAccount,
|
|
|
|
|
um.Password,
|
|
|
|
|
um.SmtpServer,
|
|
|
|
|
um.SmtpPort,
|
|
|
|
|
um.SmtpSSL,
|
|
|
|
|
UserType = "Sender"
|
|
|
|
|
}),
|
|
|
|
|
TenantDb.Queryable<SeaExport>()
|
|
|
|
|
.InnerJoin<SysUser>((s, u) => s.Doc == u.Id, "shippingweb8_dev.sys_user")
|
|
|
|
|
.Where((s, u) => s.Id == task.BusinessId && SqlFunc.Subqueryable<BusinessTaskMailSender>()
|
|
|
|
|
.Where(tms => tms.TaskMailId == mailConfig.Id && tms.IsVouchingClerk).Any())
|
|
|
|
|
.LeftJoin<CodeUserEmail>((s, u, um) => u.Id == um.CreateBy)
|
|
|
|
|
.Select((s, u, um) => new
|
|
|
|
|
{
|
|
|
|
|
u.Id,
|
|
|
|
|
u.UserName,
|
|
|
|
|
u.Phone,
|
|
|
|
|
u.Email,
|
|
|
|
|
u.SignatureHtml,
|
|
|
|
|
um.ShowName,
|
|
|
|
|
um.MailAccount,
|
|
|
|
|
um.Password,
|
|
|
|
|
um.SmtpServer,
|
|
|
|
|
um.SmtpPort,
|
|
|
|
|
um.SmtpSSL,
|
|
|
|
|
UserType = "Sender"
|
|
|
|
|
}),
|
|
|
|
|
//-----抄送人-----//
|
|
|
|
|
TenantDb.Queryable<SeaExport>()
|
|
|
|
|
.InnerJoin<SysUser>((s, u) => s.SaleId == u.Id, "shippingweb8_dev.sys_user")
|
|
|
|
|
.Where((s, u) => s.Id == task.BusinessId && SqlFunc.Subqueryable<BusinessTaskMailCC>()
|
|
|
|
|
.Where(tms => tms.TaskMailId == mailConfig.Id && tms.IsSale).Any())
|
|
|
|
|
.LeftJoin<CodeUserEmail>((s, u, um) => u.Id == um.CreateBy)
|
|
|
|
|
.Select((s, u, um) => new
|
|
|
|
|
{
|
|
|
|
|
u.Id,
|
|
|
|
|
u.UserName,
|
|
|
|
|
u.Phone,
|
|
|
|
|
u.Email,
|
|
|
|
|
u.SignatureHtml,
|
|
|
|
|
um.ShowName,
|
|
|
|
|
um.MailAccount,
|
|
|
|
|
um.Password,
|
|
|
|
|
um.SmtpServer,
|
|
|
|
|
um.SmtpPort,
|
|
|
|
|
um.SmtpSSL,
|
|
|
|
|
UserType = "CC"
|
|
|
|
|
}),
|
|
|
|
|
TenantDb.Queryable<SeaExport>()
|
|
|
|
|
.InnerJoin<SysUser>((s, u) => s.OperatorId == u.Id, "shippingweb8_dev.sys_user")
|
|
|
|
|
.Where((s, u) => s.Id == task.BusinessId && SqlFunc.Subqueryable<BusinessTaskMailCC>()
|
|
|
|
|
.Where(tms => tms.TaskMailId == mailConfig.Id && tms.IsOperator).Any())
|
|
|
|
|
.LeftJoin<CodeUserEmail>((s, u, um) => u.Id == um.CreateBy)
|
|
|
|
|
.Select((s, u, um) => new
|
|
|
|
|
{
|
|
|
|
|
u.Id,
|
|
|
|
|
u.UserName,
|
|
|
|
|
u.Phone,
|
|
|
|
|
u.Email,
|
|
|
|
|
u.SignatureHtml,
|
|
|
|
|
um.ShowName,
|
|
|
|
|
um.MailAccount,
|
|
|
|
|
um.Password,
|
|
|
|
|
um.SmtpServer,
|
|
|
|
|
um.SmtpPort,
|
|
|
|
|
um.SmtpSSL,
|
|
|
|
|
UserType = "CC"
|
|
|
|
|
}),
|
|
|
|
|
TenantDb.Queryable<SeaExport>()
|
|
|
|
|
.InnerJoin<SysUser>((s, u) => s.CustomerService == u.Id, "shippingweb8_dev.sys_user")
|
|
|
|
|
.Where((s, u) => s.Id == task.BusinessId && SqlFunc.Subqueryable<BusinessTaskMailCC>()
|
|
|
|
|
.Where(tms => tms.TaskMailId == mailConfig.Id && tms.IsCustomerService).Any())
|
|
|
|
|
.LeftJoin<CodeUserEmail>((s, u, um) => u.Id == um.CreateBy)
|
|
|
|
|
.Select((s, u, um) => new
|
|
|
|
|
{
|
|
|
|
|
u.Id,
|
|
|
|
|
u.UserName,
|
|
|
|
|
u.Phone,
|
|
|
|
|
u.Email,
|
|
|
|
|
u.SignatureHtml,
|
|
|
|
|
um.ShowName,
|
|
|
|
|
um.MailAccount,
|
|
|
|
|
um.Password,
|
|
|
|
|
um.SmtpServer,
|
|
|
|
|
um.SmtpPort,
|
|
|
|
|
um.SmtpSSL,
|
|
|
|
|
UserType = "CC"
|
|
|
|
|
}),
|
|
|
|
|
TenantDb.Queryable<SeaExport>()
|
|
|
|
|
.InnerJoin<SysUser>((s, u) => s.Doc == u.Id, "shippingweb8_dev.sys_user")
|
|
|
|
|
.Where((s, u) => s.Id == task.BusinessId && SqlFunc.Subqueryable<BusinessTaskMailCC>()
|
|
|
|
|
.Where(tms => tms.TaskMailId == mailConfig.Id && tms.IsVouchingClerk).Any())
|
|
|
|
|
.LeftJoin<CodeUserEmail>((s, u, um) => u.Id == um.CreateBy)
|
|
|
|
|
.Select((s, u, um) => new
|
|
|
|
|
{
|
|
|
|
|
u.Id,
|
|
|
|
|
u.UserName,
|
|
|
|
|
u.Phone,
|
|
|
|
|
u.Email,
|
|
|
|
|
u.SignatureHtml,
|
|
|
|
|
um.ShowName,
|
|
|
|
|
um.MailAccount,
|
|
|
|
|
um.Password,
|
|
|
|
|
um.SmtpServer,
|
|
|
|
|
um.SmtpPort,
|
|
|
|
|
um.SmtpSSL,
|
|
|
|
|
UserType = "CC"
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
var userList = await query.GroupBy(x => new { x.Id, x.UserType }).ToListAsync();
|
|
|
|
|
var senderConfig = userList.Find(x => x.UserType == "Sender");
|
|
|
|
|
if (senderConfig == null)
|
|
|
|
|
return DataResult<MailDraft>.Failed($"发件人用户:{templateModel.Sender.DisplayName} 未设置SMTP发件信息");
|
|
|
|
|
return DataResult<MailDraft>.Failed("邮件模板未设置发件人");
|
|
|
|
|
|
|
|
|
|
templateModel.Sender.MailAddress = senderConfig.MailAccount;
|
|
|
|
|
List<string> ccList = [];
|
|
|
|
|
if (mailConfig.CC != null)
|
|
|
|
|
templateModel.Sender = new MailSender
|
|
|
|
|
{
|
|
|
|
|
//设置抄送人
|
|
|
|
|
List<long> ccIds = [];
|
|
|
|
|
if (mailConfig.CC.IsSale)
|
|
|
|
|
ccIds.Add(order.SaleId);
|
|
|
|
|
else if (mailConfig.CC.IsOperator)
|
|
|
|
|
ccIds.Add(order.OperatorId);
|
|
|
|
|
else if (mailConfig.CC.IsCustomerService)
|
|
|
|
|
ccIds.Add(order.CustomerService);
|
|
|
|
|
else if (mailConfig.CC.IsVouchingClerk)
|
|
|
|
|
ccIds.Add(order.Doc);
|
|
|
|
|
|
|
|
|
|
if (ccIds.Count > 0)
|
|
|
|
|
ccList = await Db.Queryable<SysUser>().Where(x => ccIds.Contains(x.Id)).Select(x => x.Email).ToListAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//设置收件人
|
|
|
|
|
if (mailConfig.Receivers == null || mailConfig.Receivers.Count == 0)
|
|
|
|
|
return DataResult<MailDraft>.Failed("邮件模板未设置收件人");
|
|
|
|
|
DisplayName = senderConfig.UserName,
|
|
|
|
|
Phone = senderConfig.Phone,
|
|
|
|
|
SignatureHtml = senderConfig.SignatureHtml,
|
|
|
|
|
MailAddress = senderConfig.MailAccount
|
|
|
|
|
};
|
|
|
|
|
List<string> ccList = userList.Where(x => x.UserType == "CC").Select(x => x.Email).ToList();
|
|
|
|
|
|
|
|
|
|
var receiverTypes = mailConfig.Receivers.Select(x => x.Value);
|
|
|
|
|
templateModel.Receivers = await TenantDb.Queryable<BusinessOrderContact>().Where(x => receiverTypes.Contains(x.CustomerType)
|
|
|
|
|
&& x.Email != null && x.Email != string.Empty && x.BusinessId == templateModel.BusinessId && x.BusinessType == templateModel.BusinessType)
|
|
|
|
|
.Select(x => new MailReceiver { DisplayName = x.Name, MailAddress = x.Email }).ToListAsync();
|
|
|
|
|
templateModel.Receivers = await TenantDb.Queryable<BusinessOrderContact>()
|
|
|
|
|
.Where(oc => SqlFunc.Subqueryable<BusinessTaskMailReceiver>().InnerJoin<BusinessTaskMail>(
|
|
|
|
|
(tmr, tm) => tmr.TaskMailId == tm.Id).Where((tmr, tm) => tmr.Value == oc.CustomerType).Any() &&
|
|
|
|
|
!SqlFunc.IsNullOrEmpty(oc.Email) && oc.BusinessId == templateModel.BusinessId && oc.BusinessType == templateModel.BusinessType)
|
|
|
|
|
.Select(oc => new MailReceiver
|
|
|
|
|
{
|
|
|
|
|
DisplayName = oc.Name,
|
|
|
|
|
MailAddress = oc.Email
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
if (templateModel.Receivers.Count == 0)
|
|
|
|
|
return DataResult<MailDraft>.Failed("邮件模板未设置收件人或订单未填写对应联系人");
|
|
|
|
|
|
|
|
|
|
string title, content = string.Empty;
|
|
|
|
|
var razorEngine = new RazorEngine();
|
|
|
|
@ -700,6 +835,8 @@ namespace DS.WMS.Core.TaskInteraction.Method
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//插入发件人签名
|
|
|
|
|
if (!string.IsNullOrEmpty(templateModel.Sender.SignatureHtml))
|
|
|
|
|
{
|
|
|
|
|
var htmlDoc = new HtmlDocument();
|
|
|
|
|
htmlDoc.LoadHtml(content);
|
|
|
|
|
var node = htmlDoc.GetElementbyId("sign");
|
|
|
|
@ -712,25 +849,33 @@ namespace DS.WMS.Core.TaskInteraction.Method
|
|
|
|
|
content = writer.ToString();
|
|
|
|
|
writer.Close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<MailDraftAttachment> attaches = mailConfig.Attachments == null ? [] : new List<MailDraftAttachment>(mailConfig.Attachments.Count);
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
//生成模板附件
|
|
|
|
|
if (mailConfig.Attachments?.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
object? obj = templateModel.GetPropertyValue(nameof(MailTemplateModel.Primary), Flags.InstancePublic);
|
|
|
|
|
string json = JsonConvert.SerializeObject(obj ??= new { Id = templateModel.BusinessId });
|
|
|
|
|
if (json != "{}" && json != "[]")
|
|
|
|
|
{
|
|
|
|
|
if (Api.DefaultHeaders.Contains("Authorization"))
|
|
|
|
|
Api.DefaultHeaders.Remove("Authorization");
|
|
|
|
|
|
|
|
|
|
Api.DefaultHeaders.Add("Authorization", "Bearer " + User.GetToken());
|
|
|
|
|
|
|
|
|
|
string requestUrl = config["TaskMail:PrintBaseUrl"] + config["TaskMail:SQLPrint"];
|
|
|
|
|
long tenantId = long.Parse(User.TenantId);
|
|
|
|
|
string requestUrl = config["TaskMail:FileBaseUrl"] + config["TaskMail:SQLPrint"];
|
|
|
|
|
object? obj = templateModel.GetPropertyValue(nameof(MailTemplateModel.Primary), Flags.InstancePublic);
|
|
|
|
|
string json = JsonConvert.SerializeObject(obj ??= new { Id = templateModel.BusinessId });
|
|
|
|
|
|
|
|
|
|
foreach (var item in mailConfig.Attachments)
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrEmpty(item.Condition))
|
|
|
|
|
{
|
|
|
|
|
var condition = JsonConvert.DeserializeObject<ConditionContent>(item.Condition);
|
|
|
|
|
if (!actionService.Value.IsMatch(templateModel.Primary, condition))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var req = new OpenPrintReq
|
|
|
|
|
{
|
|
|
|
|
ParamJsonStr = json,
|
|
|
|
@ -739,13 +884,13 @@ namespace DS.WMS.Core.TaskInteraction.Method
|
|
|
|
|
TenantId = tenantId
|
|
|
|
|
};
|
|
|
|
|
var reqResult = await Api.PostAsync<PrintResult>(requestUrl, req);
|
|
|
|
|
if (!reqResult.Data.Succeeded)
|
|
|
|
|
return DataResult<MailDraft>.Failed($"未能获取打印API生成的文件,请求地址:{requestUrl}");
|
|
|
|
|
if (reqResult.Data == null || !reqResult.Data.Succeeded)
|
|
|
|
|
return DataResult<MailDraft>.Failed($"未能获取打印模板生成的文件,请求地址:{requestUrl}");
|
|
|
|
|
|
|
|
|
|
string url = config["TaskMail:FileBaseUrl"] + @"/PrintTempFile/" + reqResult.Data.Data;
|
|
|
|
|
string url = config["TaskMail:PrintBaseUrl"] + @"/PrintTempFile/" + reqResult.Data.Data;
|
|
|
|
|
var response = await Api.SendRequestAsync(HttpMethod.Get, url);
|
|
|
|
|
if (!response.IsSuccessStatusCode)
|
|
|
|
|
return DataResult<MailDraft>.Failed($"未能获取打印API生成的文件,附件地址:{url}");
|
|
|
|
|
return DataResult<MailDraft>.Failed($"未能获取打印模板生成的文件,附件地址:{url}");
|
|
|
|
|
|
|
|
|
|
string? fileName = Path.GetFileName(reqResult.Data.Data);
|
|
|
|
|
if (!string.IsNullOrEmpty(item.FileName)) //设置了文件名
|
|
|
|
@ -765,6 +910,9 @@ namespace DS.WMS.Core.TaskInteraction.Method
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var byteArray = await response.Content.ReadAsByteArrayAsync();
|
|
|
|
|
//if (byteArray.Length == 0)
|
|
|
|
|
// return DataResult<MailDraft>.Failed($"打印模板返回了空文件,附件地址:{url}");
|
|
|
|
|
|
|
|
|
|
attaches.Add(new MailDraftAttachment
|
|
|
|
|
{
|
|
|
|
|
AttachName = fileName,
|
|
|
|
@ -772,6 +920,7 @@ namespace DS.WMS.Core.TaskInteraction.Method
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var draft = new MailDraft
|
|
|
|
|
{
|
|
|
|
@ -783,9 +932,9 @@ namespace DS.WMS.Core.TaskInteraction.Method
|
|
|
|
|
Body = content,
|
|
|
|
|
CCTo = string.Join(";", ccList),
|
|
|
|
|
ShowName = string.IsNullOrEmpty(senderConfig.ShowName) ? templateModel.Sender.DisplayName : senderConfig.ShowName,
|
|
|
|
|
Account = senderConfig.MailAccount,
|
|
|
|
|
Password = senderConfig.Password,
|
|
|
|
|
Server = senderConfig.SmtpServer,
|
|
|
|
|
Account = senderConfig.MailAccount ?? string.Empty,
|
|
|
|
|
Password = senderConfig.Password ?? string.Empty,
|
|
|
|
|
Server = senderConfig.SmtpServer ?? string.Empty,
|
|
|
|
|
Port = senderConfig.SmtpPort.GetValueOrDefault(),
|
|
|
|
|
UseSSL = senderConfig.SmtpSSL.GetValueOrDefault(),
|
|
|
|
|
Attaches = attaches
|
|
|
|
@ -802,5 +951,91 @@ namespace DS.WMS.Core.TaskInteraction.Method
|
|
|
|
|
return DataResult<MailDraft>.FailedWithDesc(nameof(MultiLanguageConst.HttpRequestFailed));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 保存邮件草稿
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="draft">邮件草稿</param>
|
|
|
|
|
/// <param name="sendAfterSave">是否保存后发送</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult> SaveDraftAsync(MailDraft draft, bool sendAfterSave)
|
|
|
|
|
{
|
|
|
|
|
if (draft.Id != 0 && await TenantDb.Queryable<MailDraft>().AnyAsync(x => x.Id == draft.Id && x.HasSent))
|
|
|
|
|
return DataResult.Failed("禁止编辑已发送的邮件");
|
|
|
|
|
|
|
|
|
|
await TenantDb.Updateable(draft).IgnoreColumns(x => new
|
|
|
|
|
{
|
|
|
|
|
x.CreateBy,
|
|
|
|
|
x.CreateTime,
|
|
|
|
|
x.HasSent,
|
|
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
return sendAfterSave ? await SendAsync(draft) : DataResult.Success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取数据提供程序的数据输出
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="providerId">提供程序ID</param>
|
|
|
|
|
/// <param name="businessId">业务ID</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult<dynamic?>> GetProviderDataAsync(long providerId, long? businessId = null)
|
|
|
|
|
{
|
|
|
|
|
var provider = await TenantDb.Queryable<BusinessDataProvider>().FirstAsync(x => x.Id == providerId);
|
|
|
|
|
if (provider == null)
|
|
|
|
|
return DataResult<dynamic?>.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
|
|
|
|
|
|
|
|
|
|
if (businessId == null)
|
|
|
|
|
{
|
|
|
|
|
switch (provider.BusinessType)
|
|
|
|
|
{
|
|
|
|
|
case BusinessType.OceanShippingExport:
|
|
|
|
|
businessId = await TenantDb.Queryable<SeaExport>().Take(1).OrderBy(x => SqlFunc.GetRandom()).Select(x => x.Id).FirstAsync();
|
|
|
|
|
break;
|
|
|
|
|
case BusinessType.OceanShippingImport:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return DataResult<dynamic?>.FailedWithDesc(string.Format(
|
|
|
|
|
MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BusinessNotSupported)),
|
|
|
|
|
provider.BusinessType.GetDescription()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Type? type = Type.GetType(provider.TypeName, true);
|
|
|
|
|
var dataProvider = ConstructorExtensions.CreateInstance(type) as IDataProvider;
|
|
|
|
|
if (dataProvider == null)
|
|
|
|
|
return DataResult<dynamic?>.FailedWithDesc("创建数据提供程序失败:" + type.FullName);
|
|
|
|
|
|
|
|
|
|
var context = new DataFetchContext
|
|
|
|
|
{
|
|
|
|
|
BusinessId = businessId,
|
|
|
|
|
BusinessType = provider.BusinessType,
|
|
|
|
|
Content = provider.Content,
|
|
|
|
|
Db = Db,
|
|
|
|
|
TenantDb = TenantDb
|
|
|
|
|
};
|
|
|
|
|
await dataProvider.FetchDataAsync(context);
|
|
|
|
|
return DataResult<dynamic?>.Success(context.Data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 预览邮件模板
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id">邮件模板ID</param>
|
|
|
|
|
/// <param name="businessType">业务类型</param>
|
|
|
|
|
/// <param name="number">编号</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[HttpGet, Route("Preview")]
|
|
|
|
|
public async Task<DataResult<MailDraft>> PreviewAsync(long id, BusinessType businessType, string number)
|
|
|
|
|
{
|
|
|
|
|
var mailConfig = (await GetAsync(id))?.Data;
|
|
|
|
|
if (mailConfig == null)
|
|
|
|
|
return DataResult<MailDraft>.Failed($"邮件模板ID:{id} 无效");
|
|
|
|
|
|
|
|
|
|
BusinessTask task = new BusinessTask { BusinessType = businessType };
|
|
|
|
|
task.BusinessId = await TenantDb.Queryable<SeaExport>().Where(x => x.CustomerNo == number || x.MBLNO == number)
|
|
|
|
|
.Select(x => x.Id).FirstAsync();
|
|
|
|
|
|
|
|
|
|
return await CreateDraftAsync(task, mailConfig, saveDraft: false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|