ui: add B2B olmayan stok (orphans) page
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"bssapp-backend/queries"
|
||||
"bssapp-backend/utils"
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func GetProductPerformanceHandler(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, cancel := context.WithTimeout(utils.ContextWithTraceID(r.Context(), traceID), 60*time.Second)
|
||||
defer cancel()
|
||||
|
||||
f := queries.ProductPerformanceFilters{
|
||||
Search: strings.TrimSpace(r.URL.Query().Get("q")),
|
||||
ProductCode: strings.TrimSpace(r.URL.Query().Get("product_code")),
|
||||
MarketKey: strings.TrimSpace(r.URL.Query().Get("market_key")),
|
||||
Kategori: strings.TrimSpace(r.URL.Query().Get("kategori")),
|
||||
Seri: strings.TrimSpace(r.URL.Query().Get("seri")),
|
||||
Bucket: strings.TrimSpace(r.URL.Query().Get("bucket")),
|
||||
Limit: intQuery(r, "limit", 100),
|
||||
Page: intQuery(r, "page", 1),
|
||||
}
|
||||
rows, total, err := queries.ListProductPerformance(ctx, pg, f)
|
||||
if err != nil {
|
||||
http.Error(w, "urun performans listesi alinamadi: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("X-Total-Count", strconv.Itoa(total))
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"rows": rows,
|
||||
"total_count": total,
|
||||
"page": f.Page,
|
||||
"limit": f.Limit,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func GetProductPerformanceSummaryHandler(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, cancel := context.WithTimeout(utils.ContextWithTraceID(r.Context(), traceID), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
summary, err := queries.GetProductPerformanceSummary(ctx, pg)
|
||||
if err != nil {
|
||||
http.Error(w, "urun performans ozeti alinamadi: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(summary)
|
||||
}
|
||||
}
|
||||
|
||||
func GetProductPerformanceMarketsHandler(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, cancel := context.WithTimeout(utils.ContextWithTraceID(r.Context(), traceID), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
rows, err := queries.ListProductPerformanceMarkets(ctx, pg, intQuery(r, "limit", 100))
|
||||
if err != nil {
|
||||
http.Error(w, "piyasa performans ozeti alinamadi: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(rows)
|
||||
}
|
||||
}
|
||||
|
||||
func GetProductPerformanceCountriesHandler(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, cancel := context.WithTimeout(utils.ContextWithTraceID(r.Context(), traceID), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
rows, err := queries.ListProductPerformanceCountries(ctx, pg, intQuery(r, "limit", 100))
|
||||
if err != nil {
|
||||
http.Error(w, "ulke performans ozeti alinamadi: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(rows)
|
||||
}
|
||||
}
|
||||
|
||||
func GetProductPerformanceCustomersHandler(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, cancel := context.WithTimeout(utils.ContextWithTraceID(r.Context(), traceID), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
rows, err := queries.ListProductPerformanceCustomers(
|
||||
ctx,
|
||||
pg,
|
||||
strings.TrimSpace(r.URL.Query().Get("breakdown")),
|
||||
intQuery(r, "limit", 100),
|
||||
)
|
||||
if err != nil {
|
||||
http.Error(w, "musteri performans kirilimi alinamadi: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(rows)
|
||||
}
|
||||
}
|
||||
|
||||
type productPerformanceRefreshPayload struct {
|
||||
Mode string `json:"mode"`
|
||||
Stage string `json:"stage"`
|
||||
ResumeAfter int `json:"resume_after"`
|
||||
SkipDelete bool `json:"skip_delete"`
|
||||
StartDate string `json:"start_date"`
|
||||
EndDate string `json:"end_date"`
|
||||
}
|
||||
|
||||
func PostProductPerformanceRefreshHandler(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 productPerformanceRefreshPayload
|
||||
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
||||
http.Error(w, "invalid payload", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
now := time.Now()
|
||||
startDate := parseDateOrZero(payload.StartDate)
|
||||
endDate := parseDateOrZero(payload.EndDate)
|
||||
if endDate.IsZero() {
|
||||
endDate = now
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 4*time.Hour)
|
||||
defer cancel()
|
||||
result, err := queries.RefreshProductPerformance(ctx, pg, queries.ProductPerformanceRefreshRequest{
|
||||
Mode: payload.Mode,
|
||||
Stage: payload.Stage,
|
||||
ResumeAfter: payload.ResumeAfter,
|
||||
SkipDelete: payload.SkipDelete,
|
||||
StartDate: startDate,
|
||||
EndDate: endDate,
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, "urun performans refresh hatasi: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(result)
|
||||
}
|
||||
}
|
||||
|
||||
func intQuery(r *http.Request, key string, fallback int) int {
|
||||
raw := strings.TrimSpace(r.URL.Query().Get(key))
|
||||
if raw == "" {
|
||||
return fallback
|
||||
}
|
||||
n, err := strconv.Atoi(raw)
|
||||
if err != nil || n <= 0 {
|
||||
return fallback
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func parseDateOrZero(raw string) time.Time {
|
||||
raw = strings.TrimSpace(raw)
|
||||
if raw == "" {
|
||||
return time.Time{}
|
||||
}
|
||||
t, err := time.Parse("2006-01-02", raw)
|
||||
if err != nil {
|
||||
return time.Time{}
|
||||
}
|
||||
return t
|
||||
}
|
||||
Reference in New Issue
Block a user