package queries import ( "context" "database/sql" "sort" "strings" "github.com/lib/pq" ) type BrandSyncResult struct { Upserted int `json:"upserted"` Deleted int `json:"deleted"` Total int `json:"total"` } // SyncBrandsFromMSSQL pulls brand attributes from MSSQL BAGGI_V3 and upserts them into Postgres mk_brands. // Source: dbo.cdItemAttribute WHERE ItemTypeCode=1 AND AttributeTypeCode=10 func SyncBrandsFromMSSQL(ctx context.Context, mssql *sql.DB, pg *sql.DB) (BrandSyncResult, error) { out := BrandSyncResult{Upserted: 0, Deleted: 0, Total: 0} if mssql == nil || pg == nil { return out, sql.ErrConnDone } if err := EnsureBrandClassificationTables(pg); err != nil { return out, err } q := ` SELECT DISTINCT LTRIM(RTRIM(a.AttributeCode)) AS BrandCode, COALESCE(NULLIF(LTRIM(RTRIM(d.AttributeDescription)), ''), LTRIM(RTRIM(a.AttributeCode))) AS BrandName, ISNULL(a.IsBlocked, 0) AS IsBlocked FROM dbo.cdItemAttribute a WITH(NOLOCK) LEFT JOIN dbo.cdItemAttributeDesc d WITH(NOLOCK) ON d.ItemTypeCode = a.ItemTypeCode AND d.AttributeTypeCode = a.AttributeTypeCode AND d.AttributeCode = a.AttributeCode AND d.LangCode = 'TR' WHERE a.ItemTypeCode = 1 AND a.AttributeTypeCode = 10 AND ISNULL(a.IsBlocked, 0) = 0 AND LEN(LTRIM(RTRIM(a.AttributeCode))) > 0; ` rows, err := mssql.QueryContext(ctx, q) if err != nil { return out, err } defer rows.Close() type srcBrand struct { Code string Name string IsBlocked bool } src := make([]srcBrand, 0, 1024) keepCodes := make([]string, 0, 1024) seen := make(map[string]struct{}, 2048) for rows.Next() { var b srcBrand if err := rows.Scan(&b.Code, &b.Name, &b.IsBlocked); err != nil { return out, err } b.Code = strings.TrimSpace(b.Code) if b.Code == "" { continue } if _, ok := seen[b.Code]; ok { continue } seen[b.Code] = struct{}{} b.Name = strings.TrimSpace(b.Name) src = append(src, b) keepCodes = append(keepCodes, b.Code) } if err := rows.Err(); err != nil { return out, err } sort.Strings(keepCodes) out.Total = len(keepCodes) tx, err := pg.BeginTx(ctx, nil) if err != nil { return out, err } defer tx.Rollback() for _, b := range src { active := !b.IsBlocked if err := UpsertBrand(ctx, tx, b.Code, b.Name, active); err != nil { return out, err } out.Upserted++ } if len(keepCodes) > 0 { res, err := tx.ExecContext(ctx, ` DELETE FROM mk_brands WHERE brand_code NOT IN (SELECT UNNEST($1::text[])) `, pq.Array(keepCodes)) if err != nil { return out, err } if n, _ := res.RowsAffected(); n > 0 { out.Deleted = int(n) } } if err := tx.Commit(); err != nil { return out, err } return out, nil }