Merge remote-tracking branch 'origin/master'

This commit is contained in:
M_Kececi
2026-06-23 17:58:35 +03:00
parent 0f8a456ea0
commit 8d1a59f41f

View File

@@ -92,6 +92,15 @@ func productSeriesFallbackEnabled() bool {
return raw == "1" || raw == "true" || raw == "on" || raw == "yes" return raw == "1" || raw == "true" || raw == "on" || raw == "yes"
} }
func productSeriesFallbackAutoCreateEnabled() bool {
// Default on: avoid manual intervention by auto-creating the fallback dfgrp row when missing.
raw := strings.TrimSpace(strings.ToLower(os.Getenv("PRODUCT_SERIES_FALLBACK_AUTO_CREATE")))
if raw == "" {
return true
}
return raw == "1" || raw == "true" || raw == "on" || raw == "yes"
}
func productSeriesFallbackCode() string { func productSeriesFallbackCode() string {
code := strings.TrimSpace(os.Getenv("PRODUCT_SERIES_FALLBACK_SERIES_CODE")) code := strings.TrimSpace(os.Getenv("PRODUCT_SERIES_FALLBACK_SERIES_CODE"))
if code == "" { if code == "" {
@@ -141,13 +150,61 @@ LIMIT 1
`, code).Scan(&id, &gotCode) `, code).Scan(&id, &gotCode)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
// cache negative for a short period too if !productSeriesFallbackAutoCreateEnabled() {
// cache negative for a short period too
productSeriesFallbackMu.Lock()
productSeriesFallbackCachedCode = code
productSeriesFallbackCachedID = 0
productSeriesFallbackCachedAt = time.Now()
productSeriesFallbackMu.Unlock()
return 0, code, nil
}
// Auto-create the fallback series definition (best-effort) to avoid manual steps.
// We guard with the same mutex to avoid duplicate inserts within this process.
productSeriesFallbackMu.Lock() productSeriesFallbackMu.Lock()
defer productSeriesFallbackMu.Unlock()
// Re-check under lock in case another goroutine created it while we were waiting.
if productSeriesFallbackCachedCode == code && productSeriesFallbackCachedID > 0 &&
productSeriesFallbackCachedAt.After(time.Now().Add(-10*time.Minute)) {
return productSeriesFallbackCachedID, code, nil
}
var createdID int64
createErr := pg.QueryRowContext(ctx, `
INSERT INTO dfgrp (code, title, is_active, typ, master, parent_filter, sort_order, is_required, notes)
SELECT $1, $1, TRUE, 'opt', 'zbggseri', '', 0, FALSE, 'auto-created fallback series'
WHERE NOT EXISTS (
SELECT 1 FROM dfgrp WHERE master='zbggseri' AND code=$1
)
RETURNING id
`, code).Scan(&createdID)
if createErr != nil {
// If RETURNING didn't return because it already exists, select it now.
var sid int64
var scode string
selErr := pg.QueryRowContext(ctx, `
SELECT id, COALESCE(code,'')
FROM dfgrp
WHERE master='zbggseri' AND code=$1
ORDER BY id
LIMIT 1
`, code).Scan(&sid, &scode)
if selErr != nil {
// still missing; treat as disabled for now
productSeriesFallbackCachedCode = code
productSeriesFallbackCachedID = 0
productSeriesFallbackCachedAt = time.Now()
return 0, code, nil
}
createdID = sid
}
productSeriesFallbackCachedCode = code productSeriesFallbackCachedCode = code
productSeriesFallbackCachedID = 0 productSeriesFallbackCachedID = createdID
productSeriesFallbackCachedAt = time.Now() productSeriesFallbackCachedAt = time.Now()
productSeriesFallbackMu.Unlock() return createdID, code, nil
return 0, code, nil
} }
return 0, code, err return 0, code, err
} }