Files
WMS-Api/src/WMS.Web.Domain/Services/Public/SendMessageService.cs
2024-04-13 09:54:57 +08:00

398 lines
18 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using WMS.Web.Domain.IService;
using Aliyun.Acs.Core;
using Aliyun.Acs.Core.Profile;
using Aliyun.Acs.Dysmsapi.Model.V20170525;
using Aliyun.Acs.Core.Exceptions;
using WMS.Web.Core.Internal.Results;
using System.Threading.Tasks;
using WMS.Web.Domain.Options;
using Microsoft.Extensions.Options;
using MimeKit;
using MailKit.Net.Smtp;
using MailKit.Security;
using Newtonsoft.Json;
using WMS.Web.Domain.Infrastructure;
using WMS.Web.Core.Dto;
using System.Linq;
using WMS.Web.Domain.IService.Public;
using WMS.Web.Core.Dto.Erp;
using WMS.Web.Domain.Entitys;
namespace WMS.Web.Domain.Services
{
/// <summary>
/// 阿里云短息服务
/// </summary>
public class SendMessageService : ISendMessageService
{
private readonly ILogger<SendMessageService> _logger;
private readonly IClientProfile profile;
private readonly DefaultAcsClient client;
private readonly EmailOptions _emailOptions;
private readonly SmsOptions _smsOptions;
private readonly IInStockRepositories _inStockRepositories;
private readonly IInStockTaskRepositories _inStockTaskRepositories;
private readonly IErpBasicDataExtendService _erpBasicDataExtendService;
private readonly ISubscribeNotificationRepositories _subscribeNotificationRepositories;
private readonly IErpService _erpService;
public SendMessageService(ILogger<SendMessageService> logger,
IOptions<EmailOptions> emailOptions,
IOptions<SmsOptions> smsOptions,
IInStockRepositories inStockRepositories,
IErpService erpService,
IErpBasicDataExtendService erpBasicDataExtendService,
IInStockTaskRepositories inStockTaskRepositories,
ISubscribeNotificationRepositories subscribeNotificationRepositories)
{
_logger = logger;
_erpService = erpService;
_inStockRepositories = inStockRepositories;
_erpBasicDataExtendService = erpBasicDataExtendService;
_inStockTaskRepositories = inStockTaskRepositories;
_subscribeNotificationRepositories = subscribeNotificationRepositories;
_emailOptions = emailOptions?.Value;
_smsOptions = smsOptions?.Value;
profile = DefaultProfile.GetProfile("cn-hangzhou", _smsOptions.AccessKeyId, _smsOptions.AccessKeySecret);
client = new DefaultAcsClient(profile);
}
/// <summary>
/// 短信发送
/// </summary>
/// <param name="phoneNumbers"></param>
/// <param name="content"></param>
/// <returns></returns>
public Result SendSms(string phoneNumbers, string content)
{
// 构造短信请求
SendSmsRequest request = new SendSmsRequest();
request.PhoneNumbers = phoneNumbers; // 目标手机号
request.SignName = _smsOptions.SignName; // 短信签名
//request.SignName = "深圳市元创时代"; // 短信签名
request.TemplateCode = _smsOptions.TemplateCode; // 短信模板编号
request.TemplateParam = "{\"material\":\"" + content + "\"}"; // 模板参数,根据实际情况填写
try
{
// 发送短信
SendSmsResponse response = client.GetAcsResponse(request);
//isv.PARAM_LENGTH_LIMIT
if (response.Code == "OK")
{
_logger.LogInformation($"短信发送消息:成功->短信签名:{_smsOptions.SignName}->手机号码:" + phoneNumbers + " 内容:" + content);
return Result.ReSuccess();
}
else
{
_logger.LogInformation($"短信发送消息:失败->原因:{response.Message}->短信签名:{_smsOptions.SignName}->手机号码:" + phoneNumbers + " 内容:" + content);
return Result.ReFailure(response.Code, 6000);
}
}
catch (ServerException e)
{
_logger.LogInformation($"短信发送消息Server失败:{e.ErrorMessage}->手机号码:" + phoneNumbers + " 内容:" + content);
return Result.ReFailure(e.ErrorMessage, 6000);
}
catch (ClientException e)
{
_logger.LogInformation($"短信发送消息Client失败:{e.ErrorMessage}->手机号码:" + phoneNumbers + " 内容:" + content);
return Result.ReFailure(e.ErrorMessage, 6000);
}
}
/// <summary>
/// 邮箱发送消息
/// </summary>
/// <param name="toMailList"></param>
/// <param name="textBody"></param>
/// <returns></returns>
public async Task<Result> SendEmail(string mailAddress, string textBody, string coustomerName)
{
// 创建 MimeMessage 实例
MimeMessage message = new MimeMessage();
//message.From.Add(new MailboxAddress( _emailOptions.SenderName, _emailOptions.SenderEmail)); // 设置发件人姓名和邮箱地址
message.From.Add(new MailboxAddress("深圳市元创时代", _emailOptions.SenderEmail)); // 设置发件人姓名和邮箱地址
message.To.Add(new MailboxAddress(coustomerName, mailAddress)); // 设置收件人姓名和邮箱地址
//message.To.AddRange(toMailList);
//message.Subject = _emailOptions.SendTitle+$"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"; // 设置邮件主题
message.Subject = $"【深圳市元创时代】-产品入库通知{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"; // 设置邮件主题
// 创建邮件正文
BodyBuilder bodyBuilder = new BodyBuilder();
//bodyBuilder.TextBody = textBody; // 设置纯文本内容
bodyBuilder.HtmlBody = $"<p>尊敬的{coustomerName},您好,您的以下产品已入库/可安排发货:\r\n<p><p>{textBody}</p>"; // 设置 HTML 内容
message.Body = bodyBuilder.ToMessageBody();
try
{
// 连接 SMTP 服务器并发送邮件
using (SmtpClient client = new SmtpClient())
{
await client.ConnectAsync(_emailOptions.SmtpServer, _emailOptions.SmtpPort, SecureSocketOptions.StartTls); // 连接 SMTP 服务器
await client.AuthenticateAsync(_emailOptions.SenderEmail, _emailOptions.SenderEmailPwd); // 进行身份验证
await client.SendAsync(message); // 发送邮件
await client.DisconnectAsync(true); // 断开连接
}
_logger.LogInformation("邮箱发送消息:成功->收件方:" + mailAddress + " 内容:" + textBody);
return Result.ReSuccess();
}
catch (Exception ex)
{
_logger.LogInformation("邮箱发送消息:失败->收件方:" + mailAddress + " 内容:" + textBody);
return Result.ReFailure("邮箱发送:失败->收件方:"+mailAddress+",错误内容:" + ex.Message, 50006);
}
}
/// <summary>
/// 获取数据
/// </summary>
/// <returns></returns>
public async Task<(List<SendDataDto> sendDataList, List<InStockDetails> updateDetails)> GetSendContent()
{
//1.获取物料集合和组织集合和供应商的集合
var materials = new List<ErpMaterialDto>();
var materials_result = await _erpService.BillQueryForMaterial();
if (materials_result.IsSuccess)
materials = materials_result.Data.ToList();
//客户
var customerList = await _subscribeNotificationRepositories.GetList();
//要处理发送的明细
//var notSendDetails = await _inStockTaskRepositories.GetNotSendErpDetails();
var notSendDetails = await _inStockRepositories.GetNotSendDetails();
_logger.LogInformation("发送消息:要处理发送的明细->" + JsonConvert.SerializeObject(notSendDetails));
var sendDataList = new List<SendDataDto>();
if (customerList != null && customerList.Count != 0)
{
if (notSendDetails != null && notSendDetails.Count != 0)
{
//var taskIds = notSendDetails.GroupBy(x => x.Fid).Select(x => x.Key).ToList();
//var instockTotalDetails = await _inStockRepositories.GetInStockTotalDetails(taskIds);
var instockTotalDetails = notSendDetails.GroupBy(x => new { x.CustomerCode, x.MaterialNumber }).Select(x => new
{
CustomerCode = x.Key.CustomerCode,
MaterialNumber = x.Key.MaterialNumber,
TotalQty = x.Sum(t => t.Qty)
}).ToList();
foreach (var item in customerList)
{
//var current_notSendDetails = notSendDetails.Where(x => x.CustomerCode == item.CustomerNumber).ToList();
//var current_notSendDetails = instockTotalDetails.Where(x => x.CustomerCode == item.CustomerNumber).ToList();
var current_notSendDetails = instockTotalDetails.Where(x => x.CustomerCode == item.CustomerNumber).ToList();
if (current_notSendDetails != null && current_notSendDetails.Count != 0)
{
var data = new SendDataDto();
data.CustomerCode = item.CustomerNumber;
data.CustomerName = item.CustomerName;
data.PhoneNumbers = string.Join(",", item.Telephones);
data.Emails = string.Join(",", item.Emails);
foreach (var ema in item.Emails)
{
if (!string.IsNullOrEmpty(ema))
data.EmailList.Add(new MailAddress(item.CustomerName, ema));
}
foreach (var current_det in current_notSendDetails)
{
var det = new SendDataDetailsDto();
//det.TaskDetailId = current_det.Id;
det.MaterialName = _erpBasicDataExtendService.GetMaterialName(materials, current_det.MaterialNumber);
det.Specifications = _erpBasicDataExtendService.GetMaterialSpecifications(materials, current_det.MaterialNumber);
det.MaterialNumber = current_det.MaterialNumber;
//det.Qty = instockTotalDetails.Where(x => x.TaskId == current_det.Fid && x.MaterialNumber == current_det.MaterialNumber).Sum(x => x.Qty);
det.Qty = current_det.TotalQty;
data.Details.Add(det);
//if (det.Qty > 0)
// data.Details.Add(det);
}
if (data.Details.Count != 0)
sendDataList.Add(data);
}
}
}
}
return (sendDataList, notSendDetails);
}
/// <summary>
/// 执行
/// </summary>
/// <returns></returns>
public async Task<Result> Execute()
{
try
{
var update_DetailsIds = new List<int>();
var update_InstockIds = new List<int>();
var (sendContentList,updateList) = await this.GetSendContent();
if (sendContentList != null && sendContentList.Count != 0)
{
foreach (var item in sendContentList)
{
var content = "";
int i = 1;
foreach (var det in item.Details)
{
if (i == item.Details.Count)
content = content+ det.Specifications + " 数量" + Convert.ToInt32(det.Qty);
else
content = content + det.Specifications + " 数量" + Convert.ToInt32(det.Qty) + "";
i = i + 1;
}
foreach (var email in item.EmailList)
{
//邮箱
await this.SendEmail(email.Email, content, email.Name);
}
//短信
var sms_result = this.SendSms(item.PhoneNumbers, content);
//内容过长-分段发送
if (!sms_result.IsSuccess && sms_result.Message == "isv.PARAM_LENGTH_LIMIT")
{
//分段发送以字数480长度分段
//var contentParts = this.SplitContent(content, 480);
//foreach (var partContent in contentParts)
//{
// this.SendSms(item.PhoneNumbers, partContent);
//}
//1.先合并属性:规格和数量
var materials= this.MergeProperties(item.Details);
//2.按450个字分组成多个字符串集合
var contentParts = this.MergeStrings(materials);
foreach (var partContent in contentParts)
{
this.SendSms(item.PhoneNumbers, partContent);
}
}
}
update_DetailsIds = updateList.GroupBy(x=>x.Id).Select(x => x.Key).ToList();
//var inStockDetails = await _inStockRepositories.GetDetailsList(update_DetailsIds);
//if (inStockDetails != null && inStockDetails.Count != 0)
//{
// inStockDetails.ForEach(x => { x.IsHasSend = true; });
// var update_Result = await _inStockRepositories.UpdateRange(inStockDetails);
// if (!update_Result)
// {
// _logger.LogInformation("发送消息:失败-修改入库明细->" + JsonConvert.SerializeObject(inStockDetails));
// }
// else
// {
// _logger.LogInformation("发送消息:成功-修改入库明细->" + JsonConvert.SerializeObject(inStockDetails));
// }
//}
update_InstockIds = updateList.GroupBy(x => x.Fid).Select(x => x.Key).ToList();
var inStocks = await _inStockRepositories.GetList(update_InstockIds);
if (inStocks != null && inStocks.Count != 0)
{
inStocks.SelectMany(x => x.Details).Where(x=> update_DetailsIds.Contains(x.Id)).ToList().ForEach(x => { x.IsHasSend = true; });
var isSuccess = await _inStockRepositories.UpdateRange(inStocks);
if (!isSuccess)
{
_logger.LogInformation("发送消息:失败-修改入库明细->" + JsonConvert.SerializeObject(inStocks.SelectMany(x => x.Details).Where(x => update_DetailsIds.Contains(x.Id)).ToList()));
}
else
{
_logger.LogInformation("发送消息:成功-修改入库明细->" + JsonConvert.SerializeObject(inStocks.SelectMany(x => x.Details).Where(x => update_DetailsIds.Contains(x.Id)).ToList()));
}
}
}
else
_logger.LogInformation("发送消息:暂无可发送的通知明细");
return Result.ReSuccess();
}
catch (Exception ex)
{
return Result.ReFailure("发送失败:" + ex.Message, 50006);
}
}
// 将消息分割成多个部分
public List<string> SplitContent(string content, int maxLength)
{
List<string> parts = new List<string>();
for (int i = 0; i < content.Length; i += maxLength)
{
parts.Add(content.Substring(i, Math.Min(maxLength, content.Length - i)));
}
return parts;
}
/// <summary>
/// 合并属性
/// </summary>
/// <param details=""></param>
/// <returns></returns>
public List<string> MergeProperties(List<SendDataDetailsDto> details)
{
List<string> result = new List<string>();
foreach (var det in details)
{
result.Add($"{det.Specifications} 数量{Convert.ToInt32(det.Qty)}");
}
return result;
}
/// <summary>
/// 按450个字开始分组
/// </summary>
/// <param name="strings"></param>
/// <returns></returns>
public List<string> MergeStrings(List<string> strings)
{
List<string> result = new List<string>();
StringBuilder currentGroup = new StringBuilder();
foreach (var str in strings)
{
if (currentGroup.Length + str.Length > 450)
{
// 当前字符串超过50个字符将当前分组加入结果集并重置currentGroup
result.Add(currentGroup.ToString());
currentGroup.Clear();
}
// 添加当前字符串到当前分组
currentGroup.Append(str);
}
// 添加最后一个分组
if (currentGroup.Length > 0)
{
result.Add(currentGroup.ToString());
}
return result;
}
}
}