소스 검색

Minor changes to report look and report generator logic.

Added logic for sending email using Mailkit library.
master
NikolaJovanovic 3 년 전
부모
커밋
f1bb84c4c6

+ 1
- 0
BlackRockReportFunction/BlackRockReportFunction.csproj 파일 보기

<PackageReference Include="Azure.Storage.Blobs" Version="12.12.0" /> <PackageReference Include="Azure.Storage.Blobs" Version="12.12.0" />
<PackageReference Include="Azure.Storage.Queues" Version="12.10.0" /> <PackageReference Include="Azure.Storage.Queues" Version="12.10.0" />
<PackageReference Include="GemBox.Spreadsheet" Version="37.3.30.1110" /> <PackageReference Include="GemBox.Spreadsheet" Version="37.3.30.1110" />
<PackageReference Include="MailKit" Version="3.3.0" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.9" /> <PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.9" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />

+ 66
- 28
BlackRockReportFunction/Bussines/ReportGenerator.cs 파일 보기

{ {
internal class ReportGenerator internal class ReportGenerator
{ {
public static async Task<ExcelFile> GenerateReportContent()
public const string DefaultFontName = "Calibri";
public const int DefaultFontSize = 20;

public static ExcelFile GenerateReportContent()
{ {
string licenseKey = Environment.GetEnvironmentVariable("GemBoxLicenseKey"); string licenseKey = Environment.GetEnvironmentVariable("GemBoxLicenseKey");
SpreadsheetInfo.SetLicense(licenseKey); SpreadsheetInfo.SetLicense(licenseKey);
{ {
new ClockifyRecord new ClockifyRecord
{ {
recordDescription = "Description1",
recordDescription = "massa placerat duis ultricies lacus sed turpis tincidunt id aliquet risus feugiat in ante metus dictum at tempor commodo ullamcorper",
recordTime = new TimeOnly(3,15,44), recordTime = new TimeOnly(3,15,44),
amount = 200 amount = 200
}, },
new ClockifyRecord new ClockifyRecord
{ {
recordDescription = "Description1",
recordDescription = "et tortor at risus viverra adipiscing at in tellus integer feugiat scelerisque varius morbi enim nunc faucibus a pellentesque sit",
recordTime = new TimeOnly(3,15,44), recordTime = new TimeOnly(3,15,44),
amount = 150 amount = 150
} }
{ {
new ClockifyRecord new ClockifyRecord
{ {
recordDescription = "Description1",
recordDescription = "iaculis urna id volutpat lacus laoreet non curabitur gravida arcu ac tortor dignissim convallis aenean et tortor at risus viverra",
recordTime = new TimeOnly(3,15,44), recordTime = new TimeOnly(3,15,44),
amount = 300 amount = 300
}, },
new ClockifyRecord new ClockifyRecord
{ {
recordDescription = "Description1",
recordDescription = "gravida arcu ac tortor dignissim convallis aenean et tortor at risus viverra adipiscing at in tellus integer feugiat scelerisque varius",
recordTime = new TimeOnly(3,15,44), recordTime = new TimeOnly(3,15,44),
amount = 100 amount = 100
}, },
new ClockifyRecord new ClockifyRecord
{ {
recordDescription = "Description1",
recordDescription = "sit amet massa vitae tortor condimentum lacinia quis vel eros donec ac odio tempor orci dapibus ultrices in iaculis nunc",
recordTime = new TimeOnly(3,15,44), recordTime = new TimeOnly(3,15,44),
amount = 120 amount = 120
} }
{ {
new ClockifyRecord new ClockifyRecord
{ {
recordDescription = "Description1",
recordDescription = "vulputate mi sit amet mauris commodo quis imperdiet massa tincidunt nunc pulvinar sapien et ligula ullamcorper malesuada proin libero nunc",
recordTime = new TimeOnly(3,15,44), recordTime = new TimeOnly(3,15,44),
amount = 50 amount = 50
}, },
new ClockifyRecord new ClockifyRecord
{ {
recordDescription = "Description1",
recordDescription = "senectus et netus et malesuada fames ac turpis egestas maecenas pharetra convallis posuere morbi leo urna molestie at elementum eu",
recordTime = new TimeOnly(3,15,44), recordTime = new TimeOnly(3,15,44),
amount = 500 amount = 500
} }
}; };


var excelFile = new ExcelFile(); var excelFile = new ExcelFile();

var ws = excelFile.Worksheets.Add("Content"); var ws = excelFile.Worksheets.Add("Content");


var sectionStyle = new CellStyle var sectionStyle = new CellStyle
{ {
Font = Font =
{ {
Name = DefaultFontName,
Weight = ExcelFont.BoldWeight, Weight = ExcelFont.BoldWeight,
Size = 250,
Size = DefaultFontSize * 12,
}, },
VerticalAlignment = VerticalAlignmentStyle.Center, VerticalAlignment = VerticalAlignmentStyle.Center,
HorizontalAlignment = HorizontalAlignmentStyle.Center,
HorizontalAlignment = HorizontalAlignmentStyle.Left,
}; };


var mainDetailsStyle = new CellStyle var mainDetailsStyle = new CellStyle
{ {
Font = Font =
{ {
Name = DefaultFontName,
Weight = ExcelFont.BoldWeight, Weight = ExcelFont.BoldWeight,
Size = 200,
}
Size = DefaultFontSize * 11,
},
VerticalAlignment = VerticalAlignmentStyle.Center,
};

var normalDetailsStyle = new CellStyle
{
Font =
{
Name = DefaultFontName,
Weight = ExcelFont.NormalWeight,
Size = DefaultFontSize * 10,
},
VerticalAlignment = VerticalAlignmentStyle.Center,
}; };


await AddReportItems(testObject, ws, sectionStyle, mainDetailsStyle);
AddReportItems(testObject, ws, sectionStyle, mainDetailsStyle, normalDetailsStyle);


// Autofit // Autofit
excelFile = await AutoFitReport(excelFile);
AutoFitReport(excelFile);


return excelFile; return excelFile;
} }


public static async Task AddReportItems(ClockifyReport reportObject, ExcelWorksheet ws, CellStyle sectionStyle, CellStyle mainDetailsStyle)
public static void AddReportItems(ClockifyReport reportObject, ExcelWorksheet ws, CellStyle sectionStyle, CellStyle mainDetailsStyle, CellStyle normalDetailsStyle)
{ {
int row = 0; int row = 0;
string[] sectionNames = { "User", "Description", "Time (h)", "Time (decimal)", "Amount (USD)" };
string[] sectionNames = { "User ", "Description ", "Time (h) ", "Time (decimal) ", "Amount (USD) " };
decimal totalAmountSum = 0; decimal totalAmountSum = 0;
List<string> usersDecimalHours = new List<string>();


for (int i = 0; i < sectionNames.Length; i++) for (int i = 0; i < sectionNames.Length; i++)
{ {
ws.Cells[row, i].Style = sectionStyle; ws.Cells[row, i].Style = sectionStyle;
ws.Cells[row, i].Value = sectionNames[i]; ws.Cells[row, i].Value = sectionNames[i];
ws.Cells[row, i].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Medium;
ws.Cells[row, i].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Thin;
ws.Cells[row, i].Style.Borders[IndividualBorder.Bottom].LineStyle = LineStyle.Thick; ws.Cells[row, i].Style.Borders[IndividualBorder.Bottom].LineStyle = LineStyle.Thick;
ws.Cells[row, i].Style.Borders[IndividualBorder.Bottom].LineColor = System.Drawing.Color.LightGray;
} }


row++; row++;
foreach (var reportPerson in reportObject.reportPeople) foreach (var reportPerson in reportObject.reportPeople)
{ {
ws.Cells[row, 0].Style = mainDetailsStyle; ws.Cells[row, 0].Style = mainDetailsStyle;
ws.Cells[row, 0].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Thin;
ws.Cells[row, 0].Value = reportPerson.fullName; ws.Cells[row, 0].Value = reportPerson.fullName;


ws.Cells[row, 1].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Thin;

var sumOfRecordHours = Formaters.getSumOfRecordTimes(reportPerson.records.Select(record => record.recordTime).ToList()); var sumOfRecordHours = Formaters.getSumOfRecordTimes(reportPerson.records.Select(record => record.recordTime).ToList());
ws.Cells[row, 2].Style = mainDetailsStyle; ws.Cells[row, 2].Style = mainDetailsStyle;
ws.Cells[row, 2].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right; ws.Cells[row, 2].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;
ws.Cells[row, 2].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Thin;
ws.Cells[row, 2].Value = sumOfRecordHours; ws.Cells[row, 2].Value = sumOfRecordHours;


ws.Cells[row, 3].Style = mainDetailsStyle; ws.Cells[row, 3].Style = mainDetailsStyle;
ws.Cells[row, 3].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right; ws.Cells[row, 3].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;
ws.Cells[row, 3].Value = Formaters.getDecimalHours(sumOfRecordHours);
ws.Cells[row, 3].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Thin;
var userDecimalHours = Formaters.getDecimalHours(sumOfRecordHours);
ws.Cells[row, 3].Value = userDecimalHours;
usersDecimalHours.Add(userDecimalHours);


ws.Cells[row, 4].Style = mainDetailsStyle; ws.Cells[row, 4].Style = mainDetailsStyle;
ws.Cells[row, 4].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right; ws.Cells[row, 4].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;
ws.Cells[row, 4].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Thin;
ws.Cells[row, 4].Value = string.Format("{0} USD", reportPerson.records.Sum(record => record.amount).ToString("0.00")); ws.Cells[row, 4].Value = string.Format("{0} USD", reportPerson.records.Sum(record => record.amount).ToString("0.00"));
totalAmountSum += reportPerson.records.Sum(record => record.amount); totalAmountSum += reportPerson.records.Sum(record => record.amount);




foreach (var personRecord in reportPerson.records) foreach (var personRecord in reportPerson.records)
{ {
ws.Cells[row, 0].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Thin;

ws.Cells[row, 1].Style = normalDetailsStyle;
ws.Cells[row, 1].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Thin;
ws.Cells[row, 1].Value = personRecord.recordDescription; ws.Cells[row, 1].Value = personRecord.recordDescription;


ws.Cells[row, 2].Value = Formaters.getRecordTime(personRecord.recordTime);
ws.Cells[row, 2].Style = normalDetailsStyle;
ws.Cells[row, 2].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right; ws.Cells[row, 2].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;
ws.Cells[row, 2].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Thin;
ws.Cells[row, 2].Value = Formaters.getRecordTime(personRecord.recordTime);


ws.Cells[row, 3].Value = Formaters.getDecimalHours(personRecord.recordTime);
ws.Cells[row, 3].Style = normalDetailsStyle;
ws.Cells[row, 3].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right; ws.Cells[row, 3].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;
ws.Cells[row, 3].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Thin;
ws.Cells[row, 3].Value = Formaters.getDecimalHours(personRecord.recordTime);


ws.Cells[row, 4].Value = string.Format("{0} USD", personRecord.amount.ToString("0.00"));
ws.Cells[row, 4].Style = normalDetailsStyle;
ws.Cells[row, 4].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right; ws.Cells[row, 4].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;
ws.Cells[row, 4].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Thin;
ws.Cells[row, 4].Value = string.Format("{0} USD", personRecord.amount.ToString("0.00"));


row++; row++;
} }


ws.Cells.GetSubrangeAbsolute(row, 0, row, 1).Merged = true; ws.Cells.GetSubrangeAbsolute(row, 0, row, 1).Merged = true;
ws.Cells.GetSubrangeAbsolute(row, 0, row, 1).Style = mainDetailsStyle; ws.Cells.GetSubrangeAbsolute(row, 0, row, 1).Style = mainDetailsStyle;
ws.Cells.GetSubrangeAbsolute(row, 0, row, 1).Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Thin;
ws.Cells.GetSubrangeAbsolute(row, 0, row, 1).Value = reportObject.reportDescription; ws.Cells.GetSubrangeAbsolute(row, 0, row, 1).Value = reportObject.reportDescription;


var totalSum = Formaters.getTotalSum( var totalSum = Formaters.getTotalSum(


ws.Cells[row, 2].Style = mainDetailsStyle; ws.Cells[row, 2].Style = mainDetailsStyle;
ws.Cells[row, 2].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right; ws.Cells[row, 2].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;
ws.Cells[row, 2].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Thin;
ws.Cells[row, 2].Value = totalSum; ws.Cells[row, 2].Value = totalSum;


ws.Cells[row, 3].Style = mainDetailsStyle; ws.Cells[row, 3].Style = mainDetailsStyle;
ws.Cells[row, 3].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right; ws.Cells[row, 3].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;
ws.Cells[row, 3].Value = Formaters.getDecimalHours(totalSum);
ws.Cells[row, 3].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Thin;
ws.Cells[row, 3].Value = Formaters.getTotalDecimalHours(usersDecimalHours);


ws.Cells[row, 4].Style = mainDetailsStyle; ws.Cells[row, 4].Style = mainDetailsStyle;
ws.Cells[row, 4].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right; ws.Cells[row, 4].Style.HorizontalAlignment = HorizontalAlignmentStyle.Right;
ws.Cells[row, 4].Style.Borders[IndividualBorder.Right].LineStyle = LineStyle.Thin;
ws.Cells[row, 4].Value = string.Format("{0} USD", totalAmountSum.ToString("0.00")); ws.Cells[row, 4].Value = string.Format("{0} USD", totalAmountSum.ToString("0.00"));
} }


public static async Task<ExcelFile> AutoFitReport(ExcelFile excelFile)
public static void AutoFitReport(ExcelFile excelFile)
{ {
var localFile = excelFile;

foreach (var sheet in localFile.Worksheets)
foreach (var sheet in excelFile.Worksheets)
{ {
var columnCount = sheet.CalculateMaxUsedColumns(); var columnCount = sheet.CalculateMaxUsedColumns();


sheet.Columns[i].AutoFit(1, sheet.Rows[0], sheet.Rows[sheet.Rows.Count - 1]); sheet.Columns[i].AutoFit(1, sheet.Rows[0], sheet.Rows[sheet.Rows.Count - 1]);
} }
} }

return localFile;
} }
} }
} }

+ 1
- 1
BlackRockReportFunction/ClockifyApiIntegrationFunction.cs 파일 보기

} }


[Function("ClockifyApiIntegrationFunction")] [Function("ClockifyApiIntegrationFunction")]
public void Run([TimerTrigger("*/5 * * * * *")] MyInfo myTimer)
public void Run([TimerTrigger("* * * */5 * *")] MyInfo myTimer)
{ {
ClockifyReports.InitializeClockifyIntegration(); ClockifyReports.InitializeClockifyIntegration();



+ 20
- 1
BlackRockReportFunction/Helpers/Formaters.cs 파일 보기

? components[0].ToCharArray()[1].ToString() ? components[0].ToCharArray()[1].ToString()
: components[0]; : components[0];


var minutesPercent = (Convert.ToInt32(components[1]) * 100 / 60).ToString();
var totalMinutes = Convert.ToDecimal(components[1]) + (Convert.ToDecimal(components[2]) / 60);

var minutesPercent = Convert.ToInt32(Math.Floor(totalMinutes * 100 / 60)).ToString();
if (minutesPercent.Length == 1) if (minutesPercent.Length == 1)
{ {
minutesPercent = string.Format("0{0}", minutesPercent); minutesPercent = string.Format("0{0}", minutesPercent);
totalMinutes > 9 ? totalMinutes : string.Format("0{0}", totalMinutes), totalMinutes > 9 ? totalMinutes : string.Format("0{0}", totalMinutes),
totalSeconds > 9 ? totalSeconds : string.Format("0{0}", totalSeconds)); totalSeconds > 9 ? totalSeconds : string.Format("0{0}", totalSeconds));
} }

public static string getTotalDecimalHours(List<string> usersDecimalHours)
{
var minutesPercent = 0;
var hours = 0;
foreach(var userDecimalHours in usersDecimalHours)
{
var components = userDecimalHours.Split(':');
minutesPercent += Convert.ToInt32(components[1]);
hours += Convert.ToInt32(components[0]);
}

hours += minutesPercent / 100;
minutesPercent = minutesPercent % 100;

return string.Format("{0}:{1}", hours, minutesPercent);
}
} }
} }

+ 39
- 5
BlackRockReportFunction/MailSenderFunction.cs 파일 보기

using System.IO; using System.IO;
using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using SendGrid.Helpers.Mail;
//using SendGrid.Helpers.Mail;
using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs;
using MailKit;
using MimeKit;
using MimeKit.Text;
using MailKit.Net.Smtp;
using MailKit.Security;
using GemBox.Spreadsheet;


namespace BlackRockReportFunction namespace BlackRockReportFunction
{ {
//http://127.0.0.1:10000/devstoreaccount1/report-container //http://127.0.0.1:10000/devstoreaccount1/report-container


[Function("MailSenderFunction")] [Function("MailSenderFunction")]
public SendGridMessage Run([BlobTrigger("report-container/{name}", Connection = "AzureWebJobsStorage")] string fileData, string fileName)
public void Run([BlobTrigger("report-container/{name}", Connection = "AzureWebJobsStorage")] byte[] fileData)
{ {
_logger.LogInformation($"C# Blob trigger function Processed blob\n New file detected with name: {fileName}");

return null;
//var msg = new SendGridMessage() //var msg = new SendGridMessage()
//{ //{
// From = new EmailAddress("nikola.jovanovic@dilig.net", "Nikola Jovanovic"), // From = new EmailAddress("nikola.jovanovic@dilig.net", "Nikola Jovanovic"),
//msg.AddTo(new EmailAddress("nikolajovanovic3579@gmail.com", "Nikola Jovanovic")); //msg.AddTo(new EmailAddress("nikolajovanovic3579@gmail.com", "Nikola Jovanovic"));


//return msg; //return msg;
string fileName = string.Format($"BlackRockReport_{DateTime.Now.ToString("f")}.xlsx");

var email = new MimeMessage();
email.From.Add(MailboxAddress.Parse("nikola.jovanovic@dilig.net"));
email.To.Add(MailboxAddress.Parse("justine.tromp31@ethereal.email"));
email.Subject = "BlackRock Report";
var body = new TextPart(TextFormat.Html) { Text = string.Format("Here is yours report for last week. {0}", fileName) };

MemoryStream memoryStream = new MemoryStream(fileData);
memoryStream.Position = 0;

var attachment = new MimePart(" application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{
Content = new MimeContent(memoryStream),
ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
ContentTransferEncoding = ContentEncoding.Base64,
FileName = fileName
};

var multipart = new Multipart("mixed");
multipart.Add(body);
multipart.Add(attachment);
email.Body = multipart;

using var smtp = new SmtpClient();
smtp.Connect("smtp.ethereal.email", 587, SecureSocketOptions.StartTls);
smtp.Authenticate("justine.tromp31@ethereal.email", "ztbDPEp9gEfPetwZFY");
smtp.Send(email);
smtp.Disconnect(true);

_logger.LogInformation("Email sent successfully!");
} }
} }
} }

+ 7
- 2
BlackRockReportFunction/ReportGeneratorFunction.cs 파일 보기

using BlackRockReportFunction.Helpers; using BlackRockReportFunction.Helpers;
using Azure.Storage.Blobs; using Azure.Storage.Blobs;
using BlackRockReportFunction.Bussines; using BlackRockReportFunction.Bussines;
using MailKit;
using MimeKit;
using MimeKit.Text;
using MailKit.Net.Smtp;
using MailKit.Security;


namespace BlackRockReportFunction namespace BlackRockReportFunction
{ {
{ {
_logger.LogInformation($"C# Queue trigger function processed: {myQueueItem}, gemboxKey: {"E0YU - JKLB - WFCE - N52P"}"); _logger.LogInformation($"C# Queue trigger function processed: {myQueueItem}, gemboxKey: {"E0YU - JKLB - WFCE - N52P"}");


var reportFile = await ReportGenerator.GenerateReportContent();
var reportFile = ReportGenerator.GenerateReportContent();


string connection = Environment.GetEnvironmentVariable("AzureWebJobsStorage"); string connection = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
string containerName = "report-container"; string containerName = "report-container";
await blob.UploadAsync(memoryStream); await blob.UploadAsync(memoryStream);


_logger.LogInformation("File uploaded successfully!"); _logger.LogInformation("File uploaded successfully!");
}
}
} }
} }

Loading…
취소
저장