ui: add B2B olmayan stok (orphans) page
This commit is contained in:
@@ -695,13 +695,13 @@ LIMIT 1
|
||||
row.MappingReady = false
|
||||
switch {
|
||||
case row.MmitemID <= 0:
|
||||
row.MappingWarning = "B2B'de urun yok (mmitem)"
|
||||
row.MappingWarning = "B2B'de urun yok"
|
||||
case row.Dim1ID <= 0:
|
||||
row.MappingWarning = "B2B'de renk bu urunde yok (mmitem_dim/dfgrp.code)"
|
||||
row.MappingWarning = "B2B'de bu urun icin renk yok"
|
||||
case row.Dim3Code != "" && row.Dim3ID <= 0:
|
||||
row.MappingWarning = "B2B'de dim3 token eslesmesi yok (mk_dim_token_map: dimval3)"
|
||||
row.MappingWarning = "B2B'de ikinci renk eslesmesi yok"
|
||||
case !comboOK:
|
||||
row.MappingWarning = "B2B'de varyant kombosu yok (mmitem_dim)"
|
||||
row.MappingWarning = "B2B'de bu urun/renk/ikinci renk kombinasyonu yok"
|
||||
default:
|
||||
// Not an orphan; skip.
|
||||
if baseReady && comboOK {
|
||||
@@ -861,7 +861,7 @@ func PostProductSeriesMappingsSaveHandler(pg *sql.DB) http.HandlerFunc {
|
||||
}
|
||||
mmitemID, err := resolveMmitemIDTx(ctx, tx, code)
|
||||
if err != nil || mmitemID <= 0 {
|
||||
http.Error(w, "PG urun bulunamadi: "+code, http.StatusBadRequest)
|
||||
http.Error(w, "B2B urun bulunamadi: "+code, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
// Authoritative dim1 resolver: only allow saving against a color that exists for this product in mmitem_dim.
|
||||
|
||||
@@ -134,6 +134,12 @@ type TranslateSelectedPayload struct {
|
||||
Limit int `json:"limit"`
|
||||
}
|
||||
|
||||
type RuntimeTranslationsResponse struct {
|
||||
Lang string `json:"lang"`
|
||||
ByKey map[string]string `json:"by_key"`
|
||||
ByText map[string]string `json:"by_text"`
|
||||
}
|
||||
|
||||
type BulkUpdateItem struct {
|
||||
ID int64 `json:"id"`
|
||||
SourceTextTR *string `json:"source_text_tr"`
|
||||
@@ -296,6 +302,82 @@ ORDER BY t_key, lang_code
|
||||
}
|
||||
}
|
||||
|
||||
func GetRuntimeTranslationsHandler(db *sql.DB) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
lang := normalizeRuntimeTranslationLang(firstNonEmpty(
|
||||
r.URL.Query().Get("lang"),
|
||||
r.Header.Get("Accept-Language"),
|
||||
))
|
||||
if lang == "" {
|
||||
lang = "tr"
|
||||
}
|
||||
|
||||
resp := RuntimeTranslationsResponse{
|
||||
Lang: lang,
|
||||
ByKey: map[string]string{},
|
||||
ByText: map[string]string{},
|
||||
}
|
||||
|
||||
rows, err := db.Query(`
|
||||
WITH base AS (
|
||||
SELECT DISTINCT ON (t_key)
|
||||
t_key,
|
||||
COALESCE(NULLIF(source_text_tr, ''), translated_text, '') AS source_text_tr
|
||||
FROM mk_translator
|
||||
WHERE COALESCE(NULLIF(source_text_tr, ''), translated_text, '') <> ''
|
||||
ORDER BY t_key, CASE WHEN lang_code='tr' THEN 0 ELSE 1 END, updated_at DESC
|
||||
),
|
||||
target AS (
|
||||
SELECT DISTINCT ON (t_key)
|
||||
t_key,
|
||||
COALESCE(translated_text, '') AS translated_text
|
||||
FROM mk_translator
|
||||
WHERE lang_code=$1
|
||||
ORDER BY t_key, is_manual DESC, updated_at DESC
|
||||
)
|
||||
SELECT
|
||||
base.t_key,
|
||||
base.source_text_tr,
|
||||
CASE
|
||||
WHEN $1 = 'tr' THEN base.source_text_tr
|
||||
ELSE COALESCE(NULLIF(target.translated_text, ''), base.source_text_tr)
|
||||
END AS display_text
|
||||
FROM base
|
||||
LEFT JOIN target ON target.t_key = base.t_key
|
||||
`, lang)
|
||||
if err != nil {
|
||||
http.Error(w, "runtime translations query error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var key, sourceText, displayText string
|
||||
if err := rows.Scan(&key, &sourceText, &displayText); err != nil {
|
||||
http.Error(w, "runtime translations scan error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
key = strings.TrimSpace(key)
|
||||
sourceText = normalizeRuntimeTranslationText(sourceText)
|
||||
displayText = normalizeRuntimeTranslationText(displayText)
|
||||
if key != "" && displayText != "" {
|
||||
resp.ByKey[key] = displayText
|
||||
}
|
||||
if sourceText != "" && displayText != "" {
|
||||
resp.ByText[sourceText] = displayText
|
||||
}
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
http.Error(w, "runtime translations rows error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
_ = json.NewEncoder(w).Encode(resp)
|
||||
}
|
||||
}
|
||||
|
||||
func UpdateTranslationRowHandler(db *sql.DB) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
@@ -1667,6 +1749,30 @@ func normalizeTranslationLang(v string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func normalizeRuntimeTranslationLang(v string) string {
|
||||
raw := strings.ToLower(strings.TrimSpace(v))
|
||||
if raw == "" {
|
||||
return ""
|
||||
}
|
||||
if strings.Contains(raw, ",") {
|
||||
raw = strings.TrimSpace(strings.Split(raw, ",")[0])
|
||||
}
|
||||
if strings.Contains(raw, ";") {
|
||||
raw = strings.TrimSpace(strings.Split(raw, ";")[0])
|
||||
}
|
||||
if strings.Contains(raw, "-") {
|
||||
raw = strings.TrimSpace(strings.Split(raw, "-")[0])
|
||||
}
|
||||
if strings.Contains(raw, "_") {
|
||||
raw = strings.TrimSpace(strings.Split(raw, "_")[0])
|
||||
}
|
||||
return normalizeTranslationLang(raw)
|
||||
}
|
||||
|
||||
func normalizeRuntimeTranslationText(v string) string {
|
||||
return strings.Join(strings.Fields(strings.TrimSpace(v)), " ")
|
||||
}
|
||||
|
||||
func normalizeTranslationStatus(v string) string {
|
||||
status := strings.ToLower(strings.TrimSpace(v))
|
||||
if _, ok := translationStatusSet[status]; ok {
|
||||
|
||||
Reference in New Issue
Block a user