391 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C#
		
	
	
	
			
		
		
	
	
			391 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C#
		
	
	
	
using log4net;
 | 
						|
using Dapper;
 | 
						|
using Microsoft.Data.SqlClient;
 | 
						|
using OfficeOpenXml;
 | 
						|
using OfficeOpenXml.Export.ToDataTable;
 | 
						|
using System;
 | 
						|
using System.Collections.Generic;
 | 
						|
using System.Data;
 | 
						|
using System.Drawing;
 | 
						|
using System.Linq;
 | 
						|
using System.Net.Mail;
 | 
						|
using System.Text;
 | 
						|
using System.Threading.Tasks;
 | 
						|
 | 
						|
 | 
						|
namespace kmCustomReportsNET.ClassObj;
 | 
						|
 | 
						|
internal class ClsDobbsEmail_T1439 : IDisposable
 | 
						|
{
 | 
						|
  public string RptSaveToFolder { get; set; } = ClsConstants.KDrive + @"\Projects\Daily Report Archive";
 | 
						|
  public string Template1Path { get; set; } = ClsConstants.KDrive + @"\Projects\Daily Reports - Dobbs\T1439 Template 01.xlsx";
 | 
						|
  public string BusinessName { get; set; } = "DobbsTire";
 | 
						|
  public ClsConstants.enuReportIDs ReportID { get; internal set; } = ClsConstants.enuReportIDs.T1439;
 | 
						|
  public bool DebugMode { get; set; } = false;
 | 
						|
 | 
						|
  #region "Private Variables"
 | 
						|
  ILog appLog = LogManager.GetLogger(Program.AppName);
 | 
						|
  DataSet? ds = null;
 | 
						|
  List<string> FilesToAttach = new();
 | 
						|
  string SubjectToUse = string.Empty;
 | 
						|
  #endregion
 | 
						|
 | 
						|
  public void Dispose()
 | 
						|
  {
 | 
						|
    if (ds != null)
 | 
						|
      ds.Dispose();
 | 
						|
    ds = null;
 | 
						|
    FilesToAttach.Clear();
 | 
						|
  }
 | 
						|
 | 
						|
  public ClsDobbsEmail_T1439()
 | 
						|
  {
 | 
						|
    ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
 | 
						|
  }
 | 
						|
 | 
						|
  internal void Go()
 | 
						|
  {
 | 
						|
    if (ClsConstants.NeedToRun(ReportID.ToString()))
 | 
						|
    {
 | 
						|
      DateTimeOffset nxtRunTime;
 | 
						|
 | 
						|
      appLog.DebugFormat("{0} report is checking to see if we need to run...", ReportID.ToString());
 | 
						|
      using (var cn = new SqlConnection(kmCommonLibsCore.Constants.cnRDB))
 | 
						|
      {
 | 
						|
        bool? ReportDueNow = false;
 | 
						|
 | 
						|
        ReportDueNow = cn.ExecuteScalar<bool>("Select Top 1 [NeedToSend] From [crpt].[Dobbs_EmailContestCalendar] Where [SendReport]=@Today", new { Today = DateTime.Today });
 | 
						|
        if (ReportDueNow.HasValue && ReportDueNow.Value)
 | 
						|
        {
 | 
						|
          cn.Open();
 | 
						|
 | 
						|
          appLog.DebugFormat("{0} report is now running!", ReportID.ToString());
 | 
						|
          using (var cm = new SqlCommand("crpt.[Dobbs_T1439_EmailContests]", cn) { CommandType = CommandType.StoredProcedure, CommandTimeout = 120 })
 | 
						|
          using (var da = new SqlDataAdapter(cm))
 | 
						|
          {
 | 
						|
            //cm.Parameters.Add("@DateThruOverride", SqlDbType.Date).Value = DateTime.Parse("Oct 7, 2025");   // override the date thru date for testing
 | 
						|
            ds = new DataSet();
 | 
						|
            da.Fill(ds);
 | 
						|
          }
 | 
						|
 | 
						|
          //
 | 
						|
 | 
						|
          if (ds != null && ds.Tables.Count > 2 && ds.Tables[0].Rows.Count == 1)
 | 
						|
          {
 | 
						|
            CreateWeeklyStandings();
 | 
						|
            CreateDetailSnapshots();
 | 
						|
 | 
						|
            if (!DebugMode)
 | 
						|
            {
 | 
						|
              appLog.DebugFormat("{0} report is now sending out the email containing the report for this week.", ReportID.ToString());
 | 
						|
              SendEmails();
 | 
						|
 | 
						|
              cn.Execute("Update [crpt].[Dobbs_EmailContestCalendar] Set [NeedToSend]=0 Where [SendReport]=@Today", new { Today = DateTime.Today });
 | 
						|
            }
 | 
						|
          }
 | 
						|
 | 
						|
          // Run it at the next 7AM I can find, starting with tomorrow
 | 
						|
          nxtRunTime = new DateTimeOffset(DateTime.Today.AddDays(1));
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          // Run it at the next 7AM I can find
 | 
						|
          nxtRunTime = new DateTimeOffset(DateTime.Today);
 | 
						|
          appLog.DebugFormat("{0} report does not need to run.", ReportID.ToString());
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      while (nxtRunTime < DateTimeOffset.Now || nxtRunTime.Hour != 7)
 | 
						|
        nxtRunTime = nxtRunTime.AddHours(1);
 | 
						|
      ClsConstants.SetNextRun(ReportID.ToString(), nxtRunTime);
 | 
						|
      appLog.DebugFormat("{0} report will next check at: {1:ddd d-MMM-yyyy h:mm tt zzz}", ReportID.ToString(), nxtRunTime);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  private void CreateWeeklyStandings()
 | 
						|
  {
 | 
						|
    DataRow drDates = ds.Tables[0].Rows[0];
 | 
						|
    string xlsFilename;
 | 
						|
    int ctr = 0;
 | 
						|
 | 
						|
    SubjectToUse = string.Format("Email Capture Contest - Week {0} ({1:MMM d}-{2:MMM d}) Results", drDates["WeekNumber"], drDates["wkFrom"], drDates["wkTo"]);
 | 
						|
    xlsFilename = Path.Combine(RptSaveToFolder, string.Format("Dobbs {0:yyyy-MM MMM} Week {1} Email Contest Results.xlsx", drDates["mthTo"], drDates["WeekNumber"]));
 | 
						|
    if (File.Exists(xlsFilename))
 | 
						|
    {
 | 
						|
      string f0 = xlsFilename;
 | 
						|
      while (File.Exists(f0))
 | 
						|
      {
 | 
						|
        f0 = Path.Combine(RptSaveToFolder, string.Format("Dobbs {0:yyyy-MM MMM} Week {1} Email Contest Results - OLD{2:000}.xlsx", drDates["mthTo"], drDates["WeekNumber"], ctr));
 | 
						|
        ctr += 1;
 | 
						|
      }
 | 
						|
      File.Move(xlsFilename, f0);
 | 
						|
    }
 | 
						|
 | 
						|
    // Standings file first
 | 
						|
 | 
						|
    using (var fs = new FileStream(Template1Path, FileMode.Open))
 | 
						|
    using (var pkg = new ExcelPackage(fs))
 | 
						|
    {
 | 
						|
      ExcelWorksheet? s = null;  //pkg.Workbook.Worksheets[1];
 | 
						|
      int r = 4, rTot = ds.Tables[1].Rows.Count;
 | 
						|
 | 
						|
      if (pkg.Workbook.Worksheets.Count < 1)
 | 
						|
        s = pkg.Workbook.Worksheets.Add("Sheet1");
 | 
						|
      else
 | 
						|
        s = pkg.Workbook.Worksheets[0];
 | 
						|
 | 
						|
      s.Name = string.Format("{0:MMM-yyyy} Week {1} Results", drDates["mthTo"], drDates["WeekNumber"]);
 | 
						|
 | 
						|
      //s.Cells[1, 1].Value = string.Format("Email Contest Results\n{0:ddd MMM d} through {1:ddd MMM d, yyyy}", drDates["wkFrom"], drDates["wkTo"]);
 | 
						|
      s.Cells[1, 1].Value = string.Format("Email Contest Results through {1:ddd MMM d, yyyy}", drDates["wkFrom"], drDates["wkTo"]);
 | 
						|
      s.Cells[3, 3].Value = string.Format("Week {0}\nNew Emails", drDates["WeekNumber"]);
 | 
						|
 | 
						|
      foreach (DataRow dr in ds.Tables[1].Rows)
 | 
						|
      {
 | 
						|
        s.Cells[r, 1].Value = dr["Division"].ToString();
 | 
						|
        s.Cells[r, 2].Value = Convert.ToInt32(dr["StoreNumber"]);
 | 
						|
        s.Cells[r, 3].Value = Convert.ToInt32(dr["NewEmails"]);
 | 
						|
        s.Cells[r, 4].Value = Convert.ToInt32(dr["TransactionsGreaterThanZero"]);
 | 
						|
        s.Cells[r, 5].FormulaR1C1 = "=IF(RC[-1]=0,0,RC[-2]/RC[-1])";
 | 
						|
 | 
						|
        // Borders around each cell
 | 
						|
        using (var rng = s.Cells[r, 1, r, 5])
 | 
						|
        {
 | 
						|
          rng.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin);
 | 
						|
          rng.Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Medium;
 | 
						|
          rng.Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Medium;
 | 
						|
        }
 | 
						|
 | 
						|
        for (int c = 1; c <= 3; c++)
 | 
						|
          s.Cells[r, c].Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
 | 
						|
        s.Cells[r, 5].Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Medium);
 | 
						|
 | 
						|
        // Shading
 | 
						|
        if (r >= (rTot - 3 + 4))      // +4 since that's where we started
 | 
						|
        {
 | 
						|
          s.Cells[r, 5].Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
 | 
						|
          s.Cells[r, 5].Style.Fill.BackgroundColor.SetColor(Color.Red);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          s.Cells[r, 5].Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
 | 
						|
          s.Cells[r, 5].Style.Fill.BackgroundColor.SetColor(Color.Yellow);
 | 
						|
        }
 | 
						|
 | 
						|
        r++;
 | 
						|
      }
 | 
						|
 | 
						|
      // Totals
 | 
						|
      using (var rng = s.Cells[r, 1, r, 5])
 | 
						|
      {
 | 
						|
        rng.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin);
 | 
						|
        rng.Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Medium;
 | 
						|
        rng.Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Medium;
 | 
						|
        rng.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
 | 
						|
        rng.Style.Fill.BackgroundColor.SetColor(Color.LightGray);
 | 
						|
        rng.Style.Font.Bold = true;
 | 
						|
      }
 | 
						|
      for (int c = 1; c <= 3; c++)
 | 
						|
        s.Cells[r, c].Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
 | 
						|
      s.Cells[r, 5].Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Medium);
 | 
						|
 | 
						|
      //
 | 
						|
      s.Cells[r, 1].Value = "Totals";
 | 
						|
      s.Cells[r, 3].FormulaR1C1 = "=SUM(R4C:R[-1]C)";
 | 
						|
      s.Cells[r, 4].FormulaR1C1 = "=SUM(R4C:R[-1]C)";
 | 
						|
      s.Cells[r, 5].FormulaR1C1 = "=IF(RC[-1]=0,0,RC[-2]/RC[-1])";
 | 
						|
 | 
						|
      r++;
 | 
						|
      pkg.SaveAs(xlsFilename);
 | 
						|
      FilesToAttach.Add(xlsFilename);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  private void CreateDetailSnapshots()
 | 
						|
  {
 | 
						|
    DataRow drDates = ds.Tables[0].Rows[0];
 | 
						|
    string xlsFilename;
 | 
						|
    int ctr = 0;
 | 
						|
    List<string> cols = new() { "dtRangeHumanized;Period;@","Division;Location;@",
 | 
						|
      "TotalEmails;Total Emails;#,##0;R","NewEmails;New Emails;#,##0;R","OldEmails;Old Emails;#,##0;R",
 | 
						|
      "Transactions;;#,##0;R","TransactionsGreaterThanZero;Invoices Greater than Zero;#,##0;R","Penetration;Penetration Rate;0.0%;R"};
 | 
						|
 | 
						|
    xlsFilename = Path.Combine(RptSaveToFolder, string.Format("Dobbs {0:yyyy-MM MMM} Week {1} Email Contest Detail.xlsx", drDates["mthTo"], drDates["WeekNumber"]));
 | 
						|
    if (File.Exists(xlsFilename))
 | 
						|
    {
 | 
						|
      string f0 = xlsFilename;
 | 
						|
      while (File.Exists(f0))
 | 
						|
      {
 | 
						|
        f0 = Path.Combine(RptSaveToFolder, string.Format("Dobbs {0:yyyy-MM MMM} Week {1} Email Contest Detail - OLD{2:000}.xlsx", drDates["mthTo"], drDates["WeekNumber"], ctr));
 | 
						|
        ctr += 1;
 | 
						|
      }
 | 
						|
      File.Move(xlsFilename, f0);
 | 
						|
    }
 | 
						|
 | 
						|
    using (var fs = new FileStream(xlsFilename, FileMode.Create, FileAccess.Write, FileShare.None))
 | 
						|
    using (var pkg = new ExcelPackage(fs))
 | 
						|
    {
 | 
						|
      ExcelWorksheet? s = null;
 | 
						|
 | 
						|
      for (int tbNumber = 2; tbNumber < ds.Tables.Count; tbNumber++)
 | 
						|
      {
 | 
						|
        var dt = ds.Tables[tbNumber];
 | 
						|
        int r = 2, c;
 | 
						|
 | 
						|
        if (dt != null && dt.Rows.Count > 0)
 | 
						|
        {
 | 
						|
          if (pkg.Workbook.Worksheets.Count < (tbNumber - 1))
 | 
						|
            s = pkg.Workbook.Worksheets.Add("Sheet1");
 | 
						|
          else
 | 
						|
            s = pkg.Workbook.Worksheets[0];
 | 
						|
 | 
						|
          if (tbNumber == 2)
 | 
						|
            s.Name = string.Format("Month of {0:MMM-yyyy}", drDates["mthTo"]); //dt.Rows[0]["dtRangeHumanized"]);
 | 
						|
          else
 | 
						|
            s.Name = string.Format("Week thru {0:ddd MMM d}", dt.Rows[0]["dtTo"]);
 | 
						|
 | 
						|
          c = 0;
 | 
						|
          foreach (var col in cols)
 | 
						|
          {
 | 
						|
            var fld = col.Split(';');
 | 
						|
 | 
						|
            c++;
 | 
						|
            if (fld.Length > 2 && !string.IsNullOrWhiteSpace(fld[2]))
 | 
						|
              s.Columns[c].Style.Numberformat.Format = fld[2];
 | 
						|
            if (fld.Length > 3 && fld[3] == "R")
 | 
						|
              s.Columns[c].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right;
 | 
						|
 | 
						|
            s.Cells[1, c].Style.Numberformat.Format = "@";
 | 
						|
            s.Cells[1, c].Style.Font.Bold = true;
 | 
						|
            if (fld.Length > 1 && !string.IsNullOrWhiteSpace(fld[1]))
 | 
						|
              s.Cells[1, c].Value = fld[1];
 | 
						|
            else
 | 
						|
              s.Cells[1, c].Value = fld[0];
 | 
						|
 | 
						|
            if (fld.Length > 3 && fld[3] == "R")
 | 
						|
              s.Cells[1, c].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right;
 | 
						|
          }
 | 
						|
 | 
						|
          foreach (DataRow dr in dt.Rows)
 | 
						|
          {
 | 
						|
            c = 0;
 | 
						|
            foreach (var col in cols)
 | 
						|
            {
 | 
						|
              var fld = col.Split(';');
 | 
						|
 | 
						|
              s.Cells[r, ++c].Value = dr[fld[0]];
 | 
						|
            }
 | 
						|
            //s.Cells[r, 8].FormulaR1C1 = "=IF(RC7=0,0,RC4/RC7)";
 | 
						|
            //s.Cells[r, 8].FormulaR1C1 = "=IF(RC6-RC5=0,0,RC4/(RC6-RC5))";
 | 
						|
            s.Cells[r, 8].FormulaR1C1 = "=IF(RC[-2]-RC[-3]=0,0,RC[-4]/(RC[-2]-RC[-3]))";
 | 
						|
            r++;
 | 
						|
          }
 | 
						|
 | 
						|
          // Grand Totals
 | 
						|
          r++;
 | 
						|
          using (var rng = s.Cells[r, 1, r, 8])
 | 
						|
            rng.Style.Font.Bold = true;
 | 
						|
 | 
						|
          s.Cells[r, 2].Value = "Totals";
 | 
						|
          for (c = 3; c <= 7; c++)
 | 
						|
          {
 | 
						|
            s.Cells[r, c].FormulaR1C1 = "=SUM(R2C:R[-1]C)";
 | 
						|
          }
 | 
						|
          //s.Cells[r, 8].FormulaR1C1 = "=IF(RC7=0,0,RC4/RC7)";
 | 
						|
          //s.Cells[r, 8].FormulaR1C1 = "=IF(RC6-RC5=0,0,RC4/(RC6-RC5))";
 | 
						|
          s.Cells[r, 8].FormulaR1C1 = "=IF(RC[-2]-RC[-3]=0,0,RC[-4]/(RC[-2]-RC[-3]))";
 | 
						|
 | 
						|
          s.Cells.AutoFitColumns();
 | 
						|
          s.View.FreezePanes(2, 1);
 | 
						|
          s.Select("A2");
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      pkg.Save();//As(xlsFilename);
 | 
						|
      FilesToAttach.Add(xlsFilename);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  private void SendEmails()
 | 
						|
  {
 | 
						|
    using (var em = new kmCommonLibsCore.Emails() { SendMethod = kmCommonLibsCore.enuSendMethod.OnsiteServer, Subject = SubjectToUse })
 | 
						|
    {
 | 
						|
      string imgBackground, imgDisclaimer;
 | 
						|
      StringBuilder s0 = new(), s1 = new();
 | 
						|
 | 
						|
      em.AddAddress(kmCommonLibsCore.enuAddressType.From, "data@keymotive.us", "KeyMotive Data Services");
 | 
						|
      imgBackground = em.EmbedImageFile(ClsConstants.KDrive + @"\Projects\Daily Reports - COMMON\Background-Compass.jpg");
 | 
						|
      imgDisclaimer = em.EmbedImageFile(ClsConstants.KDrive + @"\Projects\Daily Reports - COMMON\KM_Disclaimer_2.png");
 | 
						|
 | 
						|
      s0.AppendFormat("<body background=cid:{0}>\n", imgBackground);
 | 
						|
      s0.AppendLine("Please find attached your custom business report. If you have any questions regarding this report, please reply to this message or contact your account manager.<br /><br />");
 | 
						|
      s0.AppendLine("Thank you for the opportunity to service the analytical needs of your organization!<br />");
 | 
						|
      s0.AppendLine("KeyMotive Data Services<br /><br /><br /><br />");
 | 
						|
      s0.AppendFormat("<img alt=\"\" src=\"cid:{0}\" />\n</body>", imgDisclaimer);
 | 
						|
 | 
						|
      s1.AppendFormat("Please find attached your custom business report. If you have any questions regarding this report, please reply to this message or contact your account manager.\n\n");
 | 
						|
      s1.AppendLine("Thank you for the opportunity to service the analytical needs of your organization!");
 | 
						|
      s1.AppendLine("KeyMotive Data Services");
 | 
						|
 | 
						|
      for (byte grp = 0; grp < 3; grp++)
 | 
						|
      {
 | 
						|
        string ToAudience = new[] { "", "CC", "BCC" }[grp];
 | 
						|
        string KeyName = string.Format("{0} MailTo{1} {2}", BusinessName, ToAudience, ReportID.ToString());
 | 
						|
        string k0 = ClsConstants.GetCustomerRegistryItem(KeyName);
 | 
						|
 | 
						|
        if (string.IsNullOrEmpty(k0))
 | 
						|
        {
 | 
						|
          KeyName = string.Format("{0} MailTo{1}", BusinessName, ToAudience);
 | 
						|
          k0 = ClsConstants.GetCustomerRegistryItem(KeyName);
 | 
						|
        }
 | 
						|
 | 
						|
        if (!string.IsNullOrEmpty(k0))
 | 
						|
        {
 | 
						|
          var lst = ConvertToEmailAddressList(k0);
 | 
						|
 | 
						|
          foreach (var itm in lst)
 | 
						|
          {
 | 
						|
            switch (grp)
 | 
						|
            {
 | 
						|
              case 1:
 | 
						|
                em.AddAddress(kmCommonLibsCore.enuAddressType.CC, itm.EmailAddress, itm.DisplayName);
 | 
						|
                break;
 | 
						|
              case 2:
 | 
						|
                em.AddAddress(kmCommonLibsCore.enuAddressType.BCC, itm.EmailAddress, itm.DisplayName);
 | 
						|
                break;
 | 
						|
              default:
 | 
						|
                em.AddAddress(kmCommonLibsCore.enuAddressType.To, itm.EmailAddress, itm.DisplayName);
 | 
						|
                break;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      foreach (var itm in FilesToAttach)
 | 
						|
        em.AttachFile(itm);
 | 
						|
 | 
						|
      em.HtmlBody = s0.ToString();
 | 
						|
      em.TextBody = s1.ToString();
 | 
						|
      em.Send();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  private List<MdlEmailAddress> ConvertToEmailAddressList(string RawAddressString)
 | 
						|
  {
 | 
						|
    List<MdlEmailAddress> rv = new();
 | 
						|
    if (!string.IsNullOrWhiteSpace(RawAddressString))
 | 
						|
    {
 | 
						|
      string[] k1 = RawAddressString.Split(';');
 | 
						|
 | 
						|
      foreach (var emx in k1)
 | 
						|
      {
 | 
						|
        var addr = new MailAddress(emx.Trim());
 | 
						|
 | 
						|
        rv.Add(new MdlEmailAddress() { EmailAddress = addr.Address, DisplayName = addr.DisplayName });
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    return rv;
 | 
						|
  }
 | 
						|
}
 |