package main import ( "context" "encoding/csv" "fmt" "os" "strings" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" "gorm.io/gorm/schema" ) // Product 产品实体(简化版) type Product struct { Code string `gorm:"column:code"` Name string `gorm:"column:name"` CostPrice *float64 `gorm:"column:cost_price"` } func main() { // 连接数据库 db, err := connectDB() if err != nil { fmt.Fprintf(os.Stderr, "连接数据库失败: %v\n", err) os.Exit(1) } ctx := context.Background() fmt.Println("正在查询数据库中未设置成本价的产品...") fmt.Println() // 查询没有设置成本价的产品(cost_price IS NULL 或 cost_price = 0) var products []Product err = db.WithContext(ctx). Table("product"). Select("code, name, cost_price"). Where("deleted_at IS NULL AND (cost_price IS NULL OR cost_price = 0)"). Order("code ASC"). Find(&products).Error // 如果单数表名查询失败,尝试复数表名 if err != nil { if strings.Contains(err.Error(), "does not exist") { err = db.WithContext(ctx). Table("products"). Select("code, name, cost_price"). Where("deleted_at IS NULL AND (cost_price IS NULL OR cost_price = 0)"). Order("code ASC"). Find(&products).Error } } if err != nil { fmt.Fprintf(os.Stderr, "查询失败: %v\n", err) os.Exit(1) } totalCount := len(products) fmt.Printf("找到 %d 个未设置成本价的产品\n\n", totalCount) if totalCount == 0 { fmt.Println("所有产品都已设置成本价!") return } // 打印到控制台 fmt.Println("=== 未设置成本价的产品列表 ===") fmt.Printf("%-20s %-50s %-15s\n", "产品编号", "产品名称", "成本价") fmt.Println(strings.Repeat("-", 85)) for _, p := range products { costPriceStr := "-" if p.CostPrice != nil && *p.CostPrice != 0 { costPriceStr = fmt.Sprintf("%.2f", *p.CostPrice) } productName := p.Name if productName == "" { productName = "-" } fmt.Printf("%-20s %-50s %-15s\n", p.Code, productName, costPriceStr) } fmt.Println() // 保存到 CSV 文件 csvFile, err := os.Create("missing_cost_price.csv") if err != nil { fmt.Fprintf(os.Stderr, "创建 CSV 文件失败: %v\n", err) return } defer csvFile.Close() // 写入 UTF-8 BOM csvFile.WriteString("\xEF\xBB\xBF") writer := csv.NewWriter(csvFile) defer writer.Flush() // 写入表头 headers := []string{"产品编号", "产品名称", "成本价"} if err := writer.Write(headers); err != nil { fmt.Fprintf(os.Stderr, "写入 CSV 表头失败: %v\n", err) return } // 写入数据 for _, p := range products { costPriceStr := "" if p.CostPrice != nil && *p.CostPrice != 0 { costPriceStr = fmt.Sprintf("%.2f", *p.CostPrice) } productName := p.Name if productName == "" { productName = "-" } record := []string{p.Code, productName, costPriceStr} if err := writer.Write(record); err != nil { fmt.Fprintf(os.Stderr, "写入 CSV 数据失败: %v\n", err) return } } fmt.Printf("✅ 结果已保存到: missing_cost_price.csv\n") fmt.Printf("📊 总计: %d 个产品未设置成本价\n", totalCount) } // connectDB 连接数据库 func connectDB() (*gorm.DB, error) { // 数据库连接配置 dsn := "host=1.117.67.95 user=tyapi_user password=Pg9mX4kL8nW2rT5y dbname=tyapi port=25010 sslmode=disable TimeZone=Asia/Shanghai" // 配置GORM,使用单数表名(与项目配置一致) gormConfig := &gorm.Config{ NamingStrategy: schema.NamingStrategy{ SingularTable: true, // 使用单数表名 }, Logger: logger.Default.LogMode(logger.Info), // 显示 SQL 日志 } db, err := gorm.Open(postgres.Open(dsn), gormConfig) if err != nil { return nil, fmt.Errorf("连接数据库失败: %w", err) } // 测试连接 sqlDB, err := db.DB() if err != nil { return nil, fmt.Errorf("获取数据库实例失败: %w", err) } if err := sqlDB.Ping(); err != nil { return nil, fmt.Errorf("数据库连接测试失败: %w", err) } fmt.Println("数据库连接成功") return db, nil }