Untitled

 avatar
unknown
plain_text
10 months ago
15 kB
20
Indexable
    [HttpGet("send-email-to-owner-and-reviewer")]
    public IActionResult TestSendEmailByType(string type)
    {
        // Pengaturan SMTP server
        string smtpAddress = "mail.tmt.co.id";
        int portNumber = 25;
        bool enableSSL = true; // (tidak dipakai langsung; kita pakai SecureSocketOptions)
        string emailFrom = "[email protected]";

        try
        {
            // Tentukan rentang tanggal untuk bulan sebelumnya
            DateTime currentDate = DateTime.Now;
            DateTime startDate = new DateTime(currentDate.Year, currentDate.Month, 1).AddMonths(-1); // Awal bulan sebelumnya
            DateTime endDate = startDate.AddMonths(1).AddSeconds(-1); // Akhir bulan sebelumnya

            // Tanggal batas konfirmasi (contoh: tgl 13 bulan berjalan)
            DateTime emailSubmissionDeadline = new DateTime(currentDate.Year, currentDate.Month, 13);

            // Ambil base URL PSCT
            string sqlUrlQuery = @"
            SELECT Url_Value
            FROM mt_url
            WHERE Url_Type = 'header'
              AND Url_Name = 'URL PSCT'";
            var rsUrl = ExecuteRows(sqlUrlQuery);
            if (!rsUrl.Any())
                return BadRequest("No URL found for the selected environment.");

            string baseUrl = rsUrl[0]["Url_Value"].ToString();
            string urlPSCT = rsUrl[0]["Url_Value"].ToString();

            // Tentukan query form & tujuan list page
            string tableName;
            string sqlFormQuery;
            if (type == "Upload Form")
            {
                tableName = "tr_claim_upload_form";
                baseUrl += "trclaimuploadformlist";
                sqlFormQuery = $@"
                WITH internal_agg AS (
                    SELECT 
                        Program_Code,
                        SUM(Trans_Unit_Price_USD_Extd) AS Total_Trans_Unit_Price
                    FROM tr_internal_form
                    WHERE Program_Code IS NOT NULL
                      AND Repair_Invoice_Date BETWEEN '{startDate:yyyy-MM-dd}' AND '{endDate:yyyy-MM-dd}'
                      AND Status = 'Eligible'
                    GROUP BY Program_Code
                ),
                claim_agg AS (
                    SELECT 
                        Program_Code,
                        SUM(CAT_Support_Amount) AS Total_CAT_Support_Amount
                    FROM tr_claim_upload_form
                    WHERE Repair_Invoice_Date BETWEEN '{startDate:yyyy-MM-dd}' AND '{endDate:yyyy-MM-dd}'
                    GROUP BY Program_Code
                )
                SELECT
                    i.Program_Code,
                    ISNULL(c.Total_CAT_Support_Amount, 0) AS Total_CAT_Support_Amount,
                    ISNULL(i.Total_Trans_Unit_Price,   0) AS Total_Trans_Unit_Price
                FROM internal_agg AS i
                LEFT JOIN claim_agg    AS c
                       ON i.Program_Code = c.Program_Code
                ORDER BY i.Program_Code;";
            }
            else if (type == "Manual Form")
            {
                tableName = "tr_claim_manual_form";
                baseUrl += "trclaimmanualformlist";
                // FIX: hilangkan koma sisa setelah SUM(...)
                sqlFormQuery = $@"
                SELECT 
                    Program_Code,
                    SUM(CAT_Support_Amount) AS Total_CAT_Support_Amount
                FROM {tableName}
                WHERE Repair_Invoice_Date BETWEEN '{startDate:yyyy-MM-dd}' AND '{endDate:yyyy-MM-dd}'
                GROUP BY Program_Code";
            }
            else
            {
                return BadRequest("Invalid type. Only 'Upload Form' and 'Manual Form' are supported.");
            }

            var rsForm = ExecuteRows(sqlFormQuery);
            if (!rsForm.Any())
                return BadRequest("No program codes found for the given date range.");

            // Kumpulkan nilai per Program_Code
            var programData = new Dictionary<string, (string TotalValue, string TotalTransactionValue)>();
            foreach (var row in rsForm)
            {
                var programCode = row["Program_Code"]?.ToString();
                if (string.IsNullOrWhiteSpace(programCode)) continue;

                var totalValueDecimal = decimal.TryParse(row["Total_CAT_Support_Amount"]?.ToString(), out var parsedTotalValue)
                    ? parsedTotalValue : 0m;
                var totalValue = totalValueDecimal.ToString("#,##0.00");

                var totalTransactionValue = type == "Upload Form" &&
                    decimal.TryParse(row["Total_Trans_Unit_Price"]?.ToString(), out var parsedTransactionValue)
                    ? parsedTransactionValue.ToString("#,##0.00")
                    : "N/A";

                if (!programData.ContainsKey(programCode))
                    programData[programCode] = (totalValue, totalTransactionValue);
            }

            // Ambil master program untuk mapping owner & reviewer
            string sqlMtProgram = $@"
            SELECT 
                p.Program_Code,
                p.Program_Name,
                p.Program_Desc,
                (
                    SELECT DISTINCT STUFF((
                        SELECT DISTINCT ',' + Reviewer
                        FROM mt_program AS subP
                        WHERE subP.Program_Code = p.Program_Code AND subP.Status = 1
                        FOR XML PATH(''), TYPE
                    ).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
                ) AS Reviewer,
                (
                    SELECT DISTINCT STUFF((
                        SELECT DISTINCT ',' + Program_Owner
                        FROM mt_program AS subP
                        WHERE subP.Program_Code = p.Program_Code AND subP.Status = 1
                        FOR XML PATH(''), TYPE
                    ).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
                ) AS Program_Owner
            FROM mt_program p
            WHERE p.Program_Code IN ('{string.Join("','", programData.Keys)}')
              AND p.Status = 1
              AND p.Program_Owner IS NOT NULL
            GROUP BY p.Program_Code, p.Program_Name, p.Program_Desc;";
            var rsMtProgram = ExecuteRows(sqlMtProgram);

            // Buat email mapping: email -> list program
            var emailProgramMapping = new Dictionary<string, List<(string ProgramCode, string ProgramName, string SalesRevenue, string CATSupport)>>();

            foreach (var row in rsMtProgram)
            {
                var programCode = row["Program_Code"]?.ToString();
                var programName = row["Program_Name"]?.ToString();
                var salesRevenue = type == "Upload Form" ? programData[programCode].TotalTransactionValue : "N/A";
                var catSupport = programData[programCode].TotalValue;

                var reviewers = (row["Reviewer"]?.ToString() ?? "")
                    .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                var owners = (row["Program_Owner"]?.ToString() ?? "")
                    .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                var userXUPJs = reviewers.Concat(owners)
                                         .Where(x => !string.IsNullOrWhiteSpace(x))
                                         .Distinct();

                string sqlUserQuery = $@"
                SELECT DISTINCT UserEmail
                FROM mt_user
                WHERE UserXUPJ IN ('{string.Join("','", userXUPJs)}')";
                var rsUserEmails = ExecuteRows(sqlUserQuery);

                foreach (var userRow in rsUserEmails)
                {
                    var email = userRow["UserEmail"]?.ToString();
                    if (string.IsNullOrWhiteSpace(email)) continue;

                    if (!emailProgramMapping.ContainsKey(email))
                        emailProgramMapping[email] = new List<(string, string, string, string)>();

                    emailProgramMapping[email].Add((programCode, programName, salesRevenue, catSupport));
                }
            }

            // Tambah global email (menerima semua program)
            string sqlEmailGlobal = @"
            SELECT Url_Value 
            FROM mt_url 
            WHERE Url_Type = 'email' 
              AND Url_Name = 'email for all program'";
            var rsEmailGlobal = ExecuteRows(sqlEmailGlobal);
            if (rsEmailGlobal.Any())
            {
                var globalEmailsRaw = rsEmailGlobal[0]["Url_Value"]?.ToString();
                if (!string.IsNullOrWhiteSpace(globalEmailsRaw))
                {
                    var globalEmails = globalEmailsRaw.Split(',')
                                                      .Select(e => e.Trim())
                                                      .Where(e => !string.IsNullOrWhiteSpace(e))
                                                      .Distinct();
                    var allProgramDetails = new List<(string, string, string, string)>();
                    foreach (var row in rsMtProgram)
                    {
                        var programCode = row["Program_Code"].ToString();
                        var programName = row["Program_Name"].ToString();
                        if (!programData.ContainsKey(programCode)) continue;

                        var salesRevenue = type == "Upload Form" ? programData[programCode].TotalTransactionValue : "N/A";
                        var catSupport = programData[programCode].TotalValue;
                        allProgramDetails.Add((programCode, programName, salesRevenue, catSupport));
                    }

                    foreach (var email in globalEmails)
                    {
                        if (!emailProgramMapping.ContainsKey(email))
                            emailProgramMapping[email] = new List<(string, string, string, string)>();
                        emailProgramMapping[email].AddRange(allProgramDetails);
                    }
                }
            }

            // Deduplicate per email
            foreach (var email in emailProgramMapping.Keys.ToList())
            {
                var uniqueSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
                var filteredList = new List<(string ProgramCode, string ProgramName, string SalesRevenue, string CATSupport)>();
                foreach (var prog in emailProgramMapping[email])
                {
                    string uniqueKey = $"{prog.ProgramCode}|{prog.ProgramName}|{prog.SalesRevenue}";
                    if (uniqueSet.Add(uniqueKey))
                        filteredList.Add(prog);
                }
                emailProgramMapping[email] = filteredList;
            }

            // === NEW: ambil template dari mt_url ===
            // Silakan sesuaikan Type/Name/Status sesuai kesepakatan di DB
            string sqlTemplate = @"
            SELECT TOP 1 Url_Value
            FROM mt_url
            WHERE Url_Type = 'template'
              AND Url_Name = 'PSCT_EMAIL_SUMMARY'
              AND ISNULL(Url_Status, 1) = 1
            ORDER BY id DESC";
            var rsTemplate = ExecuteRows(sqlTemplate);

            // Template default (fallback) kalau tidak ketemu di DB
            string fallbackTemplate = @"
<p>{{GREETING}}</p>
<p>Berikut summary dari masing-masing program yang eligible untuk di-claim ke Caterpillar sesuai master program yang sudah diinput pada PS Claim Tools, periode invoice date <strong>{{PERIOD}}</strong>.</p>
<p>Mohon konfirmasinya paling lambat <strong>{{DEADLINE}}</strong>, sebelum dilanjutkan ke proses submission claim ke PSCS.</p>
<table border='1' style='border-collapse: collapse; width: 100%;'>
  <thead>
    <tr>
      <th>No.</th>
      <th>Program ID</th>
      <th>Program Name</th>
      <th>Sales Volume</th>
      <th>Estimate CAT Support</th>
    </tr>
  </thead>
  <tbody>
    {{ROWS}}
  </tbody>
</table>
<p>Informasi dan transaksi lebih detail silakan mengecek pada aplikasi PS Claim Tools.</p>
<p><a href='{{LINK}}'>link PS Claim Tools</a></p>";

            string templateHtml = rsTemplate.Any()
                ? (rsTemplate[0]["Url_Value"]?.ToString() ?? fallbackTemplate)
                : fallbackTemplate;

            using (var client = new SmtpClient())
            {
                client.Connect(smtpAddress, portNumber, MailKit.Security.SecureSocketOptions.StartTls);

                foreach (var mapEntry in emailProgramMapping)
                {
                    string email = mapEntry.Key;
                    var programs = mapEntry.Value;

                    // Buat rows <tr>...</tr>
                    var sbRows = new System.Text.StringBuilder();
                    int counter = 1;
                    foreach (var program in programs)
                    {
                        sbRows.AppendLine($@"
<tr>
  <td style='text-align:center;'>{counter}</td>
  <td style='text-align:left;'>{program.ProgramCode}</td>
  <td style='text-align:left;'>{program.ProgramName}</td>
  <td style='text-align:right;'>{(program.SalesRevenue == "N/A" ? "-" : "$" + program.SalesRevenue)}</td>
  <td style='text-align:right;'>${program.CATSupport}</td>
</tr>");
                        counter++;
                    }

                    // Render template
                    string emailBody = templateHtml
                        .Replace("{{GREETING}}", "Dear User,")
                        .Replace("{{PERIOD}}", startDate.ToString("MMMM yyyy"))
                        .Replace("{{DEADLINE}}", emailSubmissionDeadline.ToString("dd MMMM yyyy"))
                        .Replace("{{ROWS}}", sbRows.ToString())
                        .Replace("{{LINK}}", urlPSCT);

                    // Kirim email
                    var message = new MimeMessage();
                    message.From.Add(new MailboxAddress("No Reply", emailFrom));
                    message.To.Add(new MailboxAddress("", email));
                    message.Subject = $"Program Summary for {type} - {startDate:MMMM yyyy}";
                    var bodyBuilder = new BodyBuilder { HtmlBody = emailBody };
                    message.Body = bodyBuilder.ToMessageBody();
                    client.Send(message);
                }

                client.Disconnect(true);
            }

            return Ok(new { Message = "Emails successfully sent to Owner and Reviewer using template." });
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { Message = "Terjadi kesalahan: " + ex.Message });
        }
    }
Editor is loading...
Leave a Comment