Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -55,8 +55,30 @@ func GetProductPricingListHandler(w http.ResponseWriter, r *http.Request) {
|
||||
Karisim: splitCSVParam(r.URL.Query().Get("karisim")),
|
||||
Marka: splitCSVParam(r.URL.Query().Get("marka")),
|
||||
}
|
||||
if len(filters.UrunAnaGrubu) > 3 {
|
||||
http.Error(w, "Urun Ana Grubu en fazla 3 secilebilir", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
includeTotal := true
|
||||
if raw := strings.TrimSpace(r.URL.Query().Get("include_total")); raw != "" {
|
||||
if raw == "0" || strings.EqualFold(raw, "false") {
|
||||
includeTotal = false
|
||||
}
|
||||
}
|
||||
// When primary group filters are present, COUNT(*) is acceptable and improves UX
|
||||
// (accurate totalCount/totalPages). Force includeTotal on.
|
||||
if len(filters.UrunIlkGrubu) > 0 || len(filters.UrunAnaGrubu) > 0 {
|
||||
includeTotal = true
|
||||
}
|
||||
|
||||
pageResult, err := queries.GetProductPricingPage(ctx, page, limit, filters)
|
||||
sortBy := strings.TrimSpace(r.URL.Query().Get("sort_by"))
|
||||
desc := true
|
||||
if raw := strings.TrimSpace(r.URL.Query().Get("desc")); raw != "" {
|
||||
if raw == "0" || strings.EqualFold(raw, "false") {
|
||||
desc = false
|
||||
}
|
||||
}
|
||||
pageResult, err := queries.GetProductPricingPage(ctx, page, limit, filters, includeTotal, sortBy, desc)
|
||||
if err != nil {
|
||||
if isPricingTimeoutLike(err, ctx.Err()) {
|
||||
log.Printf(
|
||||
@@ -101,6 +123,94 @@ func GetProductPricingListHandler(w http.ResponseWriter, r *http.Request) {
|
||||
_ = json.NewEncoder(w).Encode(pageResult.Rows)
|
||||
}
|
||||
|
||||
// GET /api/pricing/products/options?field=urunAnaGrubu&q=SER&limit=120
|
||||
func GetProductPricingFilterOptionsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
started := time.Now()
|
||||
traceID := buildPricingTraceID(r)
|
||||
w.Header().Set("X-Trace-ID", traceID)
|
||||
|
||||
claims, ok := auth.GetClaimsFromContext(r.Context())
|
||||
if !ok || claims == nil {
|
||||
log.Printf("[ProductPricingOptions] trace=%s unauthorized method=%s path=%s", traceID, r.Method, r.URL.Path)
|
||||
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 12*time.Second)
|
||||
defer cancel()
|
||||
|
||||
field := strings.TrimSpace(r.URL.Query().Get("field"))
|
||||
q := strings.TrimSpace(r.URL.Query().Get("q"))
|
||||
scopeUrunIlkGrubu := splitCSVParam(r.URL.Query().Get("urun_ilk_grubu"))
|
||||
limit := 120
|
||||
if raw := strings.TrimSpace(r.URL.Query().Get("limit")); raw != "" {
|
||||
if parsed, err := strconv.Atoi(raw); err == nil && parsed > 0 && parsed <= 200 {
|
||||
limit = parsed
|
||||
}
|
||||
}
|
||||
|
||||
items, err := queries.GetProductPricingFilterOptions(ctx, field, q, limit, scopeUrunIlkGrubu)
|
||||
if err != nil {
|
||||
if isPricingTimeoutLike(err, ctx.Err()) {
|
||||
log.Printf(
|
||||
"[ProductPricingOptions] trace=%s timeout user=%s id=%d field=%s q=%s duration_ms=%d err=%v",
|
||||
traceID,
|
||||
claims.Username,
|
||||
claims.ID,
|
||||
field,
|
||||
q,
|
||||
time.Since(started).Milliseconds(),
|
||||
err,
|
||||
)
|
||||
http.Error(w, "Urun fiyatlandirma filtre secenekleri zaman asimina ugradi", http.StatusGatewayTimeout)
|
||||
return
|
||||
}
|
||||
log.Printf(
|
||||
"[ProductPricingOptions] trace=%s query_error user=%s id=%d field=%s q=%s duration_ms=%d err=%v",
|
||||
traceID,
|
||||
claims.Username,
|
||||
claims.ID,
|
||||
field,
|
||||
q,
|
||||
time.Since(started).Milliseconds(),
|
||||
err,
|
||||
)
|
||||
http.Error(w, "Filtre secenekleri alinamadi: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
type optionItem struct {
|
||||
Label string `json:"label"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
resp := struct {
|
||||
Field string `json:"field"`
|
||||
Count int `json:"count"`
|
||||
Items []optionItem `json:"items"`
|
||||
}{
|
||||
Field: field,
|
||||
Count: len(items),
|
||||
Items: make([]optionItem, 0, len(items)),
|
||||
}
|
||||
for _, v := range items {
|
||||
resp.Items = append(resp.Items, optionItem{Label: v, Value: v})
|
||||
}
|
||||
|
||||
log.Printf(
|
||||
"[ProductPricingOptions] trace=%s success user=%s id=%d field=%s q=%s count=%d duration_ms=%d",
|
||||
traceID,
|
||||
claims.Username,
|
||||
claims.ID,
|
||||
field,
|
||||
q,
|
||||
len(items),
|
||||
time.Since(started).Milliseconds(),
|
||||
)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
_ = json.NewEncoder(w).Encode(resp)
|
||||
}
|
||||
|
||||
func buildPricingTraceID(r *http.Request) string {
|
||||
if r != nil {
|
||||
if id := strings.TrimSpace(r.Header.Get("X-Request-ID")); id != "" {
|
||||
|
||||
Reference in New Issue
Block a user