Merge remote-tracking branch 'origin/master'

This commit is contained in:
M_Kececi
2026-06-18 18:33:38 +03:00
parent 6fc7313ae6
commit 4d8a659650
7 changed files with 984 additions and 68 deletions

View File

@@ -1,6 +1,7 @@
package routes
import (
"bytes"
"context"
"database/sql"
"fmt"
@@ -14,6 +15,7 @@ import (
"bssapp-backend/models"
"bssapp-backend/queries"
"github.com/jung-kurt/gofpdf"
"github.com/lib/pq"
)
@@ -31,22 +33,43 @@ type wholesaleCampaignMailRow struct {
DiscountRate float64
}
func buildWholesaleCampaignChangeMailHTML(firstGroupCode string, rows []wholesaleCampaignMailRow, actor string, at time.Time) string {
func buildWholesaleCampaignChangeMailHTML(rows []wholesaleCampaignMailRow, actor string, at time.Time) string {
var b strings.Builder
b.WriteString(`<div style="font-family:Segoe UI, Arial, sans-serif; font-size:18px; line-height:1.35; -webkit-text-size-adjust:100%;">`)
b.WriteString(`<div style="margin-bottom:10px;">`)
b.WriteString(`<div style="font-size:22px; margin-bottom:4px;"><b>Kampanya Degisikligi</b></div>`)
b.WriteString(`<div>Urun Ilk Grubu: <b>` + htmlEscapeMini(firstGroupCode) + `</b></div>`)
if strings.TrimSpace(actor) != "" {
b.WriteString(`<div>Islem Yapan: <b>` + htmlEscapeMini(actor) + `</b></div>`)
}
b.WriteString(`<div>Tarih: <b>` + htmlEscapeMini(at.Format("02.01.2006 15:04")) + `</b></div>`)
b.WriteString(`<div>Varyant Sayisi: <b>` + fmt.Sprintf("%d", len(rows)) + `</b></div>`)
b.WriteString(`<div style="margin-top:10px;">Detaylar ekteki PDF dosyasindadir.</div>`)
b.WriteString(`</div>`)
b.WriteString(`</div>`)
return b.String()
}
func buildWholesaleCampaignChangeMailPDF(rows []wholesaleCampaignMailRow, actor string, at time.Time) ([]byte, error) {
pdf := gofpdf.New("L", "mm", "A4", "")
font := "Arial"
if err := registerDejavuFonts(pdf, "dejavu"); err == nil {
font = "dejavu"
} else {
log.Printf("[campaign-mail] pdf font fallback: %v", err)
}
pdf.SetMargins(7, 8, 7)
pdf.SetAutoPageBreak(true, 10)
pdf.AddPage()
pdf.SetFont(font, "B", 13)
pdf.CellFormat(0, 7, "Kampanya Degisikligi", "", 1, "L", false, 0, "")
pdf.SetFont(font, "", 8)
if strings.TrimSpace(actor) != "" {
pdf.CellFormat(0, 5, "Islem Yapan: "+strings.TrimSpace(actor), "", 1, "L", false, 0, "")
}
pdf.CellFormat(0, 5, "Tarih: "+at.Format("02.01.2006 15:04"), "", 1, "L", false, 0, "")
pdf.CellFormat(0, 5, fmt.Sprintf("Varyant Sayisi: %d", len(rows)), "", 1, "L", false, 0, "")
pdf.Ln(2)
b.WriteString(`<div style="max-width:100%; overflow-x:auto;">`)
b.WriteString(`<table style="border-collapse:collapse; font-size:16px; white-space:nowrap;">`)
b.WriteString(`<thead><tr>`)
heads := []string{
"MARKA GRUBU",
"MARKA",
@@ -56,13 +79,17 @@ func buildWholesaleCampaignChangeMailHTML(firstGroupCode string, rows []wholesal
"KAMPANYA",
"IND %",
}
for _, h := range heads {
b.WriteString(`<th style="border:1px solid #d0d0d0; background:#f3f3f3; padding:8px 10px; text-align:left; font-size:16px;">` + htmlEscapeMini(h) + `</th>`)
}
b.WriteString(`</tr></thead><tbody>`)
widths := []float64{35, 26, 35, 20, 20, 118, 16}
aligns := []string{"L", "L", "L", "R", "R", "L", "R"}
writePDFTableHeader(pdf, font, heads, widths)
pdf.SetFont(font, "", 7)
for _, r := range rows {
b.WriteString(`<tr>`)
if pdf.GetY() > 190 {
pdf.AddPage()
writePDFTableHeader(pdf, font, heads, widths)
pdf.SetFont(font, "", 7)
}
campaignLabel := strings.TrimSpace(r.CampaignCode)
if t := strings.TrimSpace(r.CampaignTitle); t != "" {
if campaignLabel != "" {
@@ -85,20 +112,14 @@ func buildWholesaleCampaignChangeMailHTML(firstGroupCode string, rows []wholesal
campaignLabel,
fmt.Sprintf("%.2f", r.DiscountRate),
}
for i, c := range cells {
align := "left"
if i == 3 || i == 4 || i == 6 {
align = "right"
}
b.WriteString(`<td style="border:1px solid #e0e0e0; padding:8px 10px; text-align:` + align + `;">` + htmlEscapeMini(strings.TrimSpace(c)) + `</td>`)
}
b.WriteString(`</tr>`)
writePDFTableRow(pdf, cells, widths, aligns, 5)
}
b.WriteString(`</tbody></table></div>`)
b.WriteString(`<div style="margin-top:12px; font-size:14px; color:#666;">Bu e-posta BSSApp sistemi tarafindan otomatik olusturulmustur.</div>`)
b.WriteString(`</div>`)
return b.String()
var buf bytes.Buffer
if err := pdf.Output(&buf); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// sendWholesaleCampaignChangeMails sends one mail per UrunIlkGrubu using existing pricing mail mapping tables.
@@ -334,14 +355,25 @@ ORDER BY dim_id, updated_at DESC;
return list[i].Dim3 < list[j].Dim3
})
subject := fmt.Sprintf("Kampanya Degisikligi | %s | %s | %d varyant", group, now.Format("02.01.2006 15:04"), len(list))
html := buildWholesaleCampaignChangeMailHTML(group, list, actor, now)
subject := fmt.Sprintf("Kampanya Degisikligi | %s | %d varyant", now.Format("02.01.2006 15:04"), len(list))
html := buildWholesaleCampaignChangeMailHTML(list, actor, now)
attachments := []mailer.Attachment(nil)
if data, err := buildWholesaleCampaignChangeMailPDF(list, actor, now); err != nil {
log.Printf("[campaign-mail] pdf build failed group=%s err=%v", group, err)
} else {
attachments = append(attachments, mailer.Attachment{
FileName: fmt.Sprintf("kampanya-degisikligi-%s.pdf", now.Format("20060102-1504")),
ContentType: "application/pdf",
Data: data,
})
}
stepCtx, stepCancel := context.WithTimeout(bg, 25*time.Second)
err = ml.Send(stepCtx, mailer.Message{
To: recipients,
Subject: subject,
BodyHTML: html,
To: recipients,
Subject: subject,
BodyHTML: html,
Attachments: attachments,
})
stepCancel()
if err != nil {