107 lines
2.5 KiB
Go
107 lines
2.5 KiB
Go
package queries
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// LookupTbStokExistsByCodes checks if tbStok contains records matching the given codes.
|
|
// Match rules are aligned with costing usage:
|
|
// - exact sKodu (ignoring spaces)
|
|
// - exact sModel
|
|
//
|
|
// Returns a map[code]exists.
|
|
func LookupTbStokExistsByCodes(ctx context.Context, mssqlDB *sql.DB, codes []string) (map[string]bool, error) {
|
|
if mssqlDB == nil {
|
|
return nil, fmt.Errorf("mssql db is nil")
|
|
}
|
|
norm := make([]string, 0, len(codes))
|
|
seen := map[string]struct{}{}
|
|
for _, c := range codes {
|
|
c = strings.TrimSpace(c)
|
|
if c == "" {
|
|
continue
|
|
}
|
|
if _, ok := seen[c]; ok {
|
|
continue
|
|
}
|
|
seen[c] = struct{}{}
|
|
norm = append(norm, c)
|
|
}
|
|
out := map[string]bool{}
|
|
for _, c := range norm {
|
|
out[c] = false
|
|
}
|
|
if len(norm) == 0 {
|
|
return out, nil
|
|
}
|
|
|
|
valParts := make([]string, 0, len(norm))
|
|
args := make([]any, 0, len(norm))
|
|
for i, code := range norm {
|
|
valParts = append(valParts, fmt.Sprintf("(@p%d)", i+1))
|
|
args = append(args, code)
|
|
}
|
|
|
|
// NOTE: This endpoint is a UX validation helper and must be fast.
|
|
// Keep predicates sargable: no function wrapping on tbStok columns.
|
|
//
|
|
// For "ignore spaces" behavior, we send both the original code and its no-space variant from input,
|
|
// and match via exact equality against tbStok.sKodu.
|
|
//
|
|
// IMPORTANT: We intentionally do not filter by IsBlocked here because IsBlocked is nullable and
|
|
// filtering requires OR logic, which can prevent index seeks and cause timeouts. This is a best-effort
|
|
// existence check for UX highlighting.
|
|
sqlText := fmt.Sprintf(`
|
|
WITH C AS (
|
|
SELECT
|
|
LTRIM(RTRIM(V.code)) AS code,
|
|
REPLACE(LTRIM(RTRIM(V.code)), ' ', '') AS code_nospace
|
|
FROM (VALUES %s) AS V(code)
|
|
),
|
|
HIT AS (
|
|
SELECT DISTINCT C.code
|
|
FROM C
|
|
JOIN dbo.tbStok S WITH (NOLOCK)
|
|
ON S.sKodu = C.code
|
|
OR S.sKodu = C.code_nospace
|
|
UNION
|
|
SELECT DISTINCT C.code
|
|
FROM C
|
|
JOIN dbo.tbStok S WITH (NOLOCK)
|
|
ON S.sModel = C.code
|
|
)
|
|
SELECT
|
|
C.code,
|
|
CASE WHEN H.code IS NULL THEN 0 ELSE 1 END AS existsFlag
|
|
FROM C
|
|
LEFT JOIN HIT H
|
|
ON H.code = C.code
|
|
`, strings.Join(valParts, ","))
|
|
|
|
rows, err := mssqlDB.QueryContext(ctx, sqlText, args...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
var code string
|
|
var existsFlag int
|
|
if err := rows.Scan(&code, &existsFlag); err != nil {
|
|
return nil, err
|
|
}
|
|
code = strings.TrimSpace(code)
|
|
if code == "" {
|
|
continue
|
|
}
|
|
out[code] = existsFlag == 1
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return out, nil
|
|
}
|