Files
tyapi-server/scripts/find_missing_cost_price.go
2025-11-19 13:41:41 +08:00

163 lines
4.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}