Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -9,11 +9,16 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"bssapp-backend/auth"
|
||||
"bssapp-backend/internal/mailer"
|
||||
)
|
||||
|
||||
type sendOrderMarketMailPayload struct {
|
||||
OrderHeaderID string `json:"orderHeaderID"`
|
||||
OrderHeaderID string `json:"orderHeaderID"`
|
||||
Operation string `json:"operation"`
|
||||
DeletedItems []string `json:"deletedItems"`
|
||||
UpdatedItems []string `json:"updatedItems"`
|
||||
AddedItems []string `json:"addedItems"`
|
||||
}
|
||||
|
||||
func SendOrderMarketMailHandler(pg *sql.DB, mssql *sql.DB, ml *mailer.GraphMailer) http.HandlerFunc {
|
||||
@@ -28,6 +33,11 @@ func SendOrderMarketMailHandler(pg *sql.DB, mssql *sql.DB, ml *mailer.GraphMaile
|
||||
http.Error(w, "database not initialized", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
claims, ok := auth.GetClaimsFromContext(r.Context())
|
||||
if !ok || claims == nil {
|
||||
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
var payload sendOrderMarketMailPayload
|
||||
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
||||
@@ -80,14 +90,52 @@ func SendOrderMarketMailHandler(pg *sql.DB, mssql *sql.DB, ml *mailer.GraphMaile
|
||||
marketLabel = strings.TrimSpace(marketCode)
|
||||
}
|
||||
|
||||
subject := fmt.Sprintf("Sipariş %s - %s", number, marketLabel)
|
||||
bodyHTML := fmt.Sprintf(
|
||||
`<p>Sipariş kaydı oluşturuldu/güncellendi.</p><p><b>Sipariş No:</b> %s<br/><b>Cari:</b> %s<br/><b>Piyasa:</b> %s</p><p>PDF ektedir.</p>`,
|
||||
htmlEsc(number),
|
||||
htmlEsc(currAccCode),
|
||||
htmlEsc(marketLabel),
|
||||
actor := strings.TrimSpace(claims.Username)
|
||||
if actor == "" {
|
||||
actor = strings.TrimSpace(claims.V3Username)
|
||||
}
|
||||
if actor == "" {
|
||||
actor = "Bilinmeyen Kullanici"
|
||||
}
|
||||
|
||||
op := strings.ToLower(strings.TrimSpace(payload.Operation))
|
||||
isUpdate := op == "update"
|
||||
|
||||
subjectAction := "SİPARİŞ KAYDI OLUŞTURULDU"
|
||||
if isUpdate {
|
||||
subjectAction = "SİPARİŞ GÜNCELLENDİ."
|
||||
}
|
||||
subject := fmt.Sprintf("%s kullanıcısı tarafından %s %s", actor, number, subjectAction)
|
||||
|
||||
cariDetail := ""
|
||||
customerRep := ""
|
||||
if header != nil {
|
||||
cariDetail = strings.TrimSpace(header.CurrAccName)
|
||||
customerRep = strings.TrimSpace(header.CustomerRep)
|
||||
}
|
||||
|
||||
body := make([]string, 0, 12)
|
||||
body = append(body,
|
||||
`<p>`,
|
||||
fmt.Sprintf(`<b>Cari Kodu:</b> %s<br/>`, htmlEsc(currAccCode)),
|
||||
fmt.Sprintf(`<b>Cari Detay:</b> %s<br/>`, htmlEsc(cariDetail)),
|
||||
fmt.Sprintf(`<b>Müşteri Temsilcisi:</b> %s<br/>`, htmlEsc(customerRep)),
|
||||
fmt.Sprintf(`<b>Piyasa:</b> %s`, htmlEsc(marketLabel)),
|
||||
`</p>`,
|
||||
)
|
||||
|
||||
if isUpdate {
|
||||
body = append(body,
|
||||
renderItemListHTML("Silinen Ürün Kodları", payload.DeletedItems),
|
||||
renderItemListHTML("Güncellenen Ürün Kodları", payload.UpdatedItems),
|
||||
renderItemListHTML("Eklenen Ürün Kodları", payload.AddedItems),
|
||||
)
|
||||
}
|
||||
|
||||
body = append(body, `<p><i>Bu sipariş BaggiSS App Uygulamasından oluşturulmuştur.</i></p>`)
|
||||
body = append(body, `<p>PDF ektedir.</p>`)
|
||||
bodyHTML := strings.Join(body, "\n")
|
||||
|
||||
fileNo := sanitizeFileName(number)
|
||||
if fileNo == "" {
|
||||
fileNo = orderID
|
||||
@@ -256,3 +304,31 @@ func htmlEsc(s string) string {
|
||||
)
|
||||
return r.Replace(s)
|
||||
}
|
||||
|
||||
func renderItemListHTML(title string, items []string) string {
|
||||
clean := make([]string, 0, len(items))
|
||||
seen := make(map[string]struct{}, len(items))
|
||||
for _, raw := range items {
|
||||
v := strings.TrimSpace(raw)
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[v]; ok {
|
||||
continue
|
||||
}
|
||||
seen[v] = struct{}{}
|
||||
clean = append(clean, v)
|
||||
}
|
||||
|
||||
if len(clean) == 0 {
|
||||
return fmt.Sprintf(`<p><b>%s:</b> Yok</p>`, htmlEsc(title))
|
||||
}
|
||||
|
||||
b := make([]string, 0, len(clean)+3)
|
||||
b = append(b, fmt.Sprintf(`<p><b>%s:</b><br/>`, htmlEsc(title)))
|
||||
for _, item := range clean {
|
||||
b = append(b, "- "+htmlEsc(item)+"<br/>")
|
||||
}
|
||||
b = append(b, `</p>`)
|
||||
return strings.Join(b, "\n")
|
||||
}
|
||||
|
||||
@@ -400,7 +400,68 @@ export const useOrderEntryStore = defineStore('orderentry', {
|
||||
}
|
||||
,
|
||||
|
||||
async sendOrderToMarketMails(orderId) {
|
||||
buildMailLineLabel(line) {
|
||||
if (!line || typeof line !== 'object') return ''
|
||||
|
||||
const item = String(line.ItemCode || '').trim()
|
||||
const color1 = String(line.ColorCode || '').trim()
|
||||
const color2 = String(line.ItemDim2Code || '').trim()
|
||||
const desc = String(line.LineDescription || '').trim()
|
||||
|
||||
if (!item) return ''
|
||||
|
||||
const colorPart = color2 ? `${color1}-${color2}` : color1
|
||||
return [item, colorPart, desc].filter(Boolean).join(' ')
|
||||
}
|
||||
,
|
||||
|
||||
buildOrderMailPayload(lines = [], isNew = false) {
|
||||
const uniq = (arr) => [...new Set((arr || []).map(v => String(v || '').trim()).filter(Boolean))]
|
||||
|
||||
const normalized = Array.isArray(lines) ? lines : []
|
||||
const mapLabel = (ln) => this.buildMailLineLabel(ln)
|
||||
|
||||
if (isNew) {
|
||||
return {
|
||||
operation: 'create',
|
||||
deletedItems: [],
|
||||
updatedItems: [],
|
||||
addedItems: uniq(
|
||||
normalized
|
||||
.filter(ln => !ln?._deleteSignal)
|
||||
.map(mapLabel)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const deletedItems = uniq(
|
||||
normalized
|
||||
.filter(ln => ln?._deleteSignal === true)
|
||||
.map(mapLabel)
|
||||
)
|
||||
|
||||
const updatedItems = uniq(
|
||||
normalized
|
||||
.filter(ln => !ln?._deleteSignal && !!ln?.OrderLineID && ln?._dirty === true)
|
||||
.map(mapLabel)
|
||||
)
|
||||
|
||||
const addedItems = uniq(
|
||||
normalized
|
||||
.filter(ln => !ln?._deleteSignal && !ln?.OrderLineID)
|
||||
.map(mapLabel)
|
||||
)
|
||||
|
||||
return {
|
||||
operation: 'update',
|
||||
deletedItems,
|
||||
updatedItems,
|
||||
addedItems
|
||||
}
|
||||
}
|
||||
,
|
||||
|
||||
async sendOrderToMarketMails(orderId, payload = {}) {
|
||||
const id = String(orderId || this.header?.OrderHeaderID || '').trim()
|
||||
if (!id) {
|
||||
throw new Error('Sipariş ID bulunamadı')
|
||||
@@ -408,7 +469,11 @@ export const useOrderEntryStore = defineStore('orderentry', {
|
||||
|
||||
try {
|
||||
const res = await api.post('/order/send-market-mail', {
|
||||
orderHeaderID: id
|
||||
orderHeaderID: id,
|
||||
operation: payload?.operation || 'create',
|
||||
deletedItems: Array.isArray(payload?.deletedItems) ? payload.deletedItems : [],
|
||||
updatedItems: Array.isArray(payload?.updatedItems) ? payload.updatedItems : [],
|
||||
addedItems: Array.isArray(payload?.addedItems) ? payload.addedItems : []
|
||||
})
|
||||
return res?.data || {}
|
||||
} catch (err) {
|
||||
@@ -2867,7 +2932,8 @@ export const useOrderEntryStore = defineStore('orderentry', {
|
||||
|
||||
// 📧 Piyasa eşleşen alıcılara sipariş PDF gönderimi (kayıt başarılı olduktan sonra)
|
||||
try {
|
||||
const mailRes = await this.sendOrderToMarketMails(serverOrderId)
|
||||
const mailPayload = this.buildOrderMailPayload(lines, isNew)
|
||||
const mailRes = await this.sendOrderToMarketMails(serverOrderId, mailPayload)
|
||||
const sentCount = Number(mailRes?.sentCount || 0)
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
|
||||
Reference in New Issue
Block a user