164 lines
4.8 KiB
Go
164 lines
4.8 KiB
Go
package routes
|
|
|
|
import (
|
|
"bssapp-backend/queries"
|
|
"bssapp-backend/utils"
|
|
"database/sql"
|
|
"encoding/json"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Step-1/2 scope (distinct+cascade) comes from the PostgreSQL parameter cache.
|
|
// For now we implement:
|
|
// - Postgres tables (bootstrap)
|
|
// - List/Save rules (bulk)
|
|
// - Options endpoint for cascade (mk_urunpricingprmtr)
|
|
|
|
type PricingRuleBulkSavePayload struct {
|
|
Items []queries.PricingRuleSaveItem `json:"items"`
|
|
}
|
|
|
|
func GetPricingRulesHandler(pg *sql.DB) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
traceID := utils.TraceIDFromRequest(r)
|
|
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
|
|
|
rows, err := queries.ListPricingRules(ctx, pg)
|
|
if err != nil {
|
|
http.Error(w, "pricing rules list error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
_ = json.NewEncoder(w).Encode(rows)
|
|
}
|
|
}
|
|
|
|
// Very small “bulk upsert” for step-1/2: we only need to persist the multipliers+roundings for now.
|
|
// Rules are identified by UUID; new rows can be created via empty id (server generates).
|
|
func SavePricingRulesBulkHandler(pg *sql.DB) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
|
|
var payload PricingRuleBulkSavePayload
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
http.Error(w, "invalid payload", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
traceID := utils.TraceIDFromRequest(r)
|
|
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
|
|
|
tx, err := pg.BeginTx(ctx, nil)
|
|
if err != nil {
|
|
http.Error(w, "pg transaction start error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
defer tx.Rollback()
|
|
|
|
updated := 0
|
|
for _, it := range payload.Items {
|
|
// Zero means that no rounding rule has been configured yet.
|
|
if it.TryStep < 0 || it.UsdStep < 0 || it.EurStep < 0 {
|
|
http.Error(w, "invalid rounding step", http.StatusBadRequest)
|
|
return
|
|
}
|
|
id, err := queries.UpsertPricingRule(ctx, tx, it)
|
|
if err != nil {
|
|
http.Error(w, "pricing rule save error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
if id != "" {
|
|
updated++
|
|
}
|
|
}
|
|
|
|
if err := tx.Commit(); err != nil {
|
|
http.Error(w, "pg transaction commit error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"success": true, "updated": updated})
|
|
}
|
|
}
|
|
|
|
func GetPricingRuleOptionsHandler(pg *sql.DB) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
|
|
field := strings.TrimSpace(r.URL.Query().Get("field"))
|
|
if field == "" {
|
|
http.Error(w, "missing field", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
limit := 500
|
|
if raw := strings.TrimSpace(r.URL.Query().Get("limit")); raw != "" {
|
|
if n, err := strconv.Atoi(raw); err == nil && n > 0 && n <= 5000 {
|
|
limit = n
|
|
}
|
|
}
|
|
|
|
f := pricingRuleFiltersFromRequest(r)
|
|
|
|
traceID := utils.TraceIDFromRequest(r)
|
|
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
|
|
|
opts, err := queries.ListPricingParameterDistinctOptions(ctx, pg, field, f, limit)
|
|
if err != nil {
|
|
http.Error(w, "options lookup error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
|
"field": field,
|
|
"options": opts,
|
|
})
|
|
}
|
|
}
|
|
|
|
func GetPricingParameterRulesHandler(pg *sql.DB) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
|
|
traceID := utils.TraceIDFromRequest(r)
|
|
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
|
rows, err := queries.ListPricingParameterRules(ctx, pg, pricingRuleFiltersFromRequest(r))
|
|
if err != nil {
|
|
http.Error(w, "pricing parameter rules list error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
_ = json.NewEncoder(w).Encode(rows)
|
|
}
|
|
}
|
|
|
|
func pricingRuleFiltersFromRequest(r *http.Request) queries.PricingRuleOptionFilters {
|
|
return queries.PricingRuleOptionFilters{
|
|
AskiliYan: splitCSV(r.URL.Query().Get("askili_yan")),
|
|
Kategori: splitCSV(r.URL.Query().Get("kategori")),
|
|
UrunIlkGrubu: splitCSV(r.URL.Query().Get("urun_ilk_grubu")),
|
|
UrunAnaGrubu: splitCSV(r.URL.Query().Get("urun_ana_grubu")),
|
|
UrunAltGrubu: splitCSV(r.URL.Query().Get("urun_alt_grubu")),
|
|
Icerik: splitCSV(r.URL.Query().Get("icerik")),
|
|
Marka: splitCSV(r.URL.Query().Get("marka")),
|
|
BrandCode: splitCSV(r.URL.Query().Get("brand_code")),
|
|
BrandGroupSec: splitCSV(r.URL.Query().Get("brand_group")),
|
|
}
|
|
}
|
|
|
|
func splitCSV(raw string) []string {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
return nil
|
|
}
|
|
parts := strings.Split(raw, ",")
|
|
out := make([]string, 0, len(parts))
|
|
for _, p := range parts {
|
|
p = strings.TrimSpace(p)
|
|
if p != "" {
|
|
out = append(out, p)
|
|
}
|
|
}
|
|
return out
|
|
}
|