Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
package marketing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// PresetID identifies a seasonal content-calendar preset.
|
||||
type PresetID string
|
||||
|
||||
const (
|
||||
PresetBlackFriday PresetID = "black_friday"
|
||||
PresetChristmas PresetID = "christmas"
|
||||
)
|
||||
|
||||
// CampaignStructureKey is stored on export_feeds.template JSON (no migration).
|
||||
const CampaignStructureKey = "_campaign"
|
||||
|
||||
// Preset is a dated seasonal window for preparing an export feed.
|
||||
type Preset struct {
|
||||
ID PresetID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
StartDate string `json:"start_date"`
|
||||
EndDate string `json:"end_date"`
|
||||
Year int `json:"year"`
|
||||
}
|
||||
|
||||
// StructureMeta is persisted under template._campaign.
|
||||
type StructureMeta struct {
|
||||
PresetID PresetID `json:"presetId"`
|
||||
Name string `json:"name"`
|
||||
StartDate string `json:"startDate"`
|
||||
EndDate string `json:"endDate"`
|
||||
Year int `json:"year"`
|
||||
PreparedAt string `json:"preparedAt"`
|
||||
}
|
||||
|
||||
func pad2(n int) string {
|
||||
return fmt.Sprintf("%02d", n)
|
||||
}
|
||||
|
||||
func toISODate(t time.Time) string {
|
||||
return fmt.Sprintf("%s-%s-%s", pad2(t.Year()), pad2(int(t.Month())), pad2(t.Day()))
|
||||
}
|
||||
|
||||
// BlackFridayDate returns Black Friday (day after US Thanksgiving) in UTC date parts.
|
||||
func BlackFridayDate(year int) time.Time {
|
||||
nov1 := time.Date(year, time.November, 1, 0, 0, 0, 0, time.UTC)
|
||||
dow := int(nov1.Weekday()) // Sunday=0
|
||||
firstThursday := 1 + ((4 - dow + 7) % 7)
|
||||
fourthThursday := firstThursday + 21
|
||||
return time.Date(year, time.November, fourthThursday+1, 0, 0, 0, 0, time.UTC)
|
||||
}
|
||||
|
||||
// ResolvePreset returns date window for a preset id and year.
|
||||
func ResolvePreset(id PresetID, year int) (Preset, error) {
|
||||
if year < 2000 || year > 2100 {
|
||||
return Preset{}, ClientMsg("invalid year")
|
||||
}
|
||||
switch id {
|
||||
case PresetBlackFriday:
|
||||
bf := BlackFridayDate(year)
|
||||
start := bf.AddDate(0, 0, -7)
|
||||
end := bf.AddDate(0, 0, 3)
|
||||
return Preset{
|
||||
ID: id,
|
||||
Name: "Black Friday",
|
||||
Description: "Promo window around Black Friday — prepare a Google Shopping-style export feed.",
|
||||
StartDate: toISODate(start),
|
||||
EndDate: toISODate(end),
|
||||
Year: year,
|
||||
}, nil
|
||||
case PresetChristmas:
|
||||
return Preset{
|
||||
ID: PresetChristmas,
|
||||
Name: "Christmas",
|
||||
Description: "Holiday catalog push from Dec 1 through Boxing Day.",
|
||||
StartDate: toISODate(time.Date(year, time.December, 1, 0, 0, 0, 0, time.UTC)),
|
||||
EndDate: toISODate(time.Date(year, time.December, 26, 0, 0, 0, 0, time.UTC)),
|
||||
Year: year,
|
||||
}, nil
|
||||
default:
|
||||
return Preset{}, ClientMsg("preset_id must be black_friday or christmas")
|
||||
}
|
||||
}
|
||||
|
||||
// ListPresets returns Black Friday + Christmas for the year.
|
||||
func ListPresets(year int) []Preset {
|
||||
bf, _ := ResolvePreset(PresetBlackFriday, year)
|
||||
xmas, _ := ResolvePreset(PresetChristmas, year)
|
||||
return []Preset{bf, xmas}
|
||||
}
|
||||
|
||||
// DefaultCampaignMappings are Google Shopping-ish CSV column → product field sources.
|
||||
func DefaultCampaignMappings() map[string]string {
|
||||
return map[string]string{
|
||||
"id": "product_id",
|
||||
"title": "processed_name",
|
||||
"description": "processed_description",
|
||||
"link": "attr.url",
|
||||
"image_link": "attr.image",
|
||||
"availability": "attr.availability",
|
||||
"price": "attr.price",
|
||||
"brand": "attr.brand",
|
||||
"gtin": "gtin",
|
||||
"google_product_category": "category",
|
||||
"condition": "attr.condition",
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user