Files
aura-crm/production/backend/internal/clientnotify/templates.go
T

89 lines
3.3 KiB
Go

package clientnotify
import (
"fmt"
"strings"
)
// smsMaxLen keeps every SMS variant inside a single SMS.ru segment
// (Cyrillic/UCS-2 caps a segment at 70 chars) — going over silently splits
// into (and bills as) multiple segments.
const smsMaxLen = 70
// sanitize strips characters that would break a single-line SMS or read
// oddly in a Telegram message body — same rationale as internal/lead's
// cleanField (untrusted text ends up verbatim in an outbound message).
func sanitize(s string) string {
replacer := strings.NewReplacer("\r", " ", "\n", " ", "\t", " ")
return strings.TrimSpace(replacer.Replace(s))
}
// truncate cuts s to at most n runes, preserving UTF-8 validity — a plain
// byte-slice cut could split a multi-byte Cyrillic rune in half.
func truncate(s string, n int) string {
r := []rune(s)
if len(r) <= n {
return s
}
return string(r[:n])
}
// trackingURL is appended when non-empty (settings.TrackingURL returns ""
// when PublicTrackingURL isn't configured) — every template in this file
// degrades to link-free text rather than omitting the notification
// entirely, same stance Ready already took before this.
func OrderCreated(channel, deviceLabel, trackingURL string) string {
if channel == "sms" {
msg := fmt.Sprintf("Заявка на %s принята. Следим за статусом здесь же.", deviceLabel)
if trackingURL != "" {
msg = fmt.Sprintf("Заявка на %s принята. Статус: %s", deviceLabel, trackingURL)
}
return truncate(sanitize(msg), smsMaxLen)
}
msg := fmt.Sprintf("🆕 Ваша заявка принята: %s\nМы сообщим, как только статус изменится.", deviceLabel)
if trackingURL != "" {
msg += "\n" + trackingURL
}
return msg
}
func StatusChanged(channel, deviceLabel, statusLabel, trackingURL string) string {
if channel == "sms" {
msg := fmt.Sprintf("%s: статус — %s", deviceLabel, statusLabel)
if trackingURL != "" {
msg = fmt.Sprintf("%s: статус — %s. %s", deviceLabel, statusLabel, trackingURL)
}
return truncate(sanitize(msg), smsMaxLen)
}
msg := fmt.Sprintf("🔄 %s\nНовый статус: %s", deviceLabel, statusLabel)
if trackingURL != "" {
msg += "\n" + trackingURL
}
return msg
}
func Ready(channel, deviceLabel, trackingURL string) string {
if channel == "sms" {
return truncate(sanitize(fmt.Sprintf("%s готово к выдаче! Ждём вас.", deviceLabel)), smsMaxLen)
}
msg := fmt.Sprintf("✅ %s готово к выдаче!", deviceLabel)
if trackingURL != "" {
msg += "\n" + trackingURL
}
return msg
}
func WarrantyExpiring(channel, deviceLabel, until string) string {
if channel == "sms" {
return truncate(sanitize(fmt.Sprintf("Гарантия на %s истекает %s", deviceLabel, until)), smsMaxLen)
}
return fmt.Sprintf("⏳ Гарантия на %s истекает %s. Если есть проблема — обращайтесь.", deviceLabel, until)
}
func LoyaltyAccrued(channel string, points int) string {
if channel == "sms" {
return truncate(sanitize(fmt.Sprintf("Начислено %d бонусных баллов", points)), smsMaxLen)
}
return fmt.Sprintf("🎁 Вам начислено %d бонусных баллов. Спишите их на следующий заказ.", points)
}