add new processor
This commit is contained in:
603
scripts/analyze_processors.go
Normal file
603
scripts/analyze_processors.go
Normal file
@@ -0,0 +1,603 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
|
||||
// ProcessorInfo 处理器信息
|
||||
type ProcessorInfo struct {
|
||||
ProductCode string // 产品编号(从文件名提取)
|
||||
ProductName string // 产品名称(从数据库查询)
|
||||
Category string // 分类(从数据库查询)
|
||||
Price string // 价格(从数据库查询)
|
||||
DataSource string // 数据源(根据service确定)
|
||||
DataSourceCode string // 数据源编号(CallAPI的第一个参数)
|
||||
CostPrice string // 成本价(留空)
|
||||
}
|
||||
|
||||
// Product 产品实体(简化版)
|
||||
type Product struct {
|
||||
Code string `gorm:"column:code"`
|
||||
Name string `gorm:"column:name"`
|
||||
CategoryID string `gorm:"column:category_id"`
|
||||
Category *ProductCategory `gorm:"foreignKey:CategoryID"`
|
||||
Price decimal.Decimal `gorm:"column:price"`
|
||||
}
|
||||
|
||||
// ProductCategory 产品分类实体(简化版)
|
||||
type ProductCategory struct {
|
||||
ID string `gorm:"column:id"`
|
||||
Name string `gorm:"column:name"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 获取处理器目录
|
||||
processorsDir := filepath.Join("internal", "domains", "api", "services", "processors")
|
||||
if len(os.Args) > 1 {
|
||||
processorsDir = os.Args[1]
|
||||
}
|
||||
|
||||
// 扫描所有处理器文件
|
||||
processors, err := scanProcessors(processorsDir)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "扫描处理器失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 连接数据库
|
||||
db, err := connectDB()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "连接数据库失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 检查数据库产品数量和处理器数量
|
||||
ctx := context.Background()
|
||||
checkProductAndProcessorCounts(ctx, db, processors)
|
||||
|
||||
// 查询产品信息并填充
|
||||
fmt.Println("正在查询数据库...")
|
||||
successCount := 0
|
||||
for i := range processors {
|
||||
product, err := queryProduct(ctx, db, processors[i].ProductCode)
|
||||
if err == nil && product != nil && product.Name != "" {
|
||||
processors[i].ProductName = product.Name
|
||||
if product.Category != nil && product.Category.Name != "" {
|
||||
processors[i].Category = product.Category.Name
|
||||
}
|
||||
// 格式化价格,保留两位小数
|
||||
if !product.Price.IsZero() {
|
||||
processors[i].Price = product.Price.String()
|
||||
}
|
||||
successCount++
|
||||
} else {
|
||||
// 如果查询失败,保留空值(不输出错误,避免日志过多)
|
||||
processors[i].ProductName = ""
|
||||
processors[i].Category = ""
|
||||
processors[i].Price = ""
|
||||
}
|
||||
}
|
||||
fmt.Printf("成功查询到 %d/%d 个产品的信息\n", successCount, len(processors))
|
||||
|
||||
// 按数据源排序
|
||||
sortProcessorsByDataSource(processors)
|
||||
|
||||
// 输出表格
|
||||
printTable(processors)
|
||||
|
||||
// 同时输出到文件
|
||||
writeToFiles(processors)
|
||||
}
|
||||
|
||||
// sortProcessorsByDataSource 按数据源排序
|
||||
func sortProcessorsByDataSource(processors []ProcessorInfo) {
|
||||
// 定义数据源的排序优先级
|
||||
dataSourceOrder := map[string]int{
|
||||
"安徽智查": 1,
|
||||
"羽山数据": 2,
|
||||
"西部数据": 3,
|
||||
"四川星维": 4,
|
||||
"天眼查": 5,
|
||||
"阿里云": 6,
|
||||
"木子数据": 7,
|
||||
"内部处理": 8,
|
||||
"未知": 9,
|
||||
}
|
||||
|
||||
sort.Slice(processors, func(i, j int) bool {
|
||||
orderI, existsI := dataSourceOrder[processors[i].DataSource]
|
||||
orderJ, existsJ := dataSourceOrder[processors[j].DataSource]
|
||||
|
||||
// 如果数据源不存在,放在最后
|
||||
if !existsI {
|
||||
orderI = 999
|
||||
}
|
||||
if !existsJ {
|
||||
orderJ = 999
|
||||
}
|
||||
|
||||
// 首先按数据源排序
|
||||
if orderI != orderJ {
|
||||
return orderI < orderJ
|
||||
}
|
||||
|
||||
// 如果数据源相同,按产品编号排序
|
||||
return processors[i].ProductCode < processors[j].ProductCode
|
||||
})
|
||||
}
|
||||
|
||||
// writeToFiles 将表格写入文件
|
||||
func writeToFiles(processors []ProcessorInfo) {
|
||||
// 写入 CSV 文件
|
||||
csvFile, err := os.Create("processors_table.csv")
|
||||
if err == nil {
|
||||
defer csvFile.Close()
|
||||
csvFile.WriteString("\xEF\xBB\xBF") // UTF-8 BOM
|
||||
csvFile.WriteString("产品编号,产品名称,分类,价格,数据源,数据源编号,成本价\n")
|
||||
for _, p := range processors {
|
||||
productName := strings.ReplaceAll(p.ProductName, ",", ",")
|
||||
category := strings.ReplaceAll(p.Category, ",", ",")
|
||||
csvFile.WriteString(fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s\n",
|
||||
p.ProductCode,
|
||||
productName,
|
||||
category,
|
||||
p.Price,
|
||||
p.DataSource,
|
||||
p.DataSourceCode,
|
||||
p.CostPrice))
|
||||
}
|
||||
fmt.Println("\n✅ CSV 文件已保存到: processors_table.csv")
|
||||
}
|
||||
|
||||
// 写入 Markdown 文件
|
||||
mdFile, err := os.Create("processors_table.md")
|
||||
if err == nil {
|
||||
defer mdFile.Close()
|
||||
mdFile.WriteString("# 处理器产品信息表\n\n")
|
||||
mdFile.WriteString("| 产品编号 | 产品名称 | 分类 | 价格 | 数据源 | 数据源编号 | 成本价 |\n")
|
||||
mdFile.WriteString("|---------|---------|------|------|--------|-----------|--------|\n")
|
||||
for _, p := range processors {
|
||||
productName := p.ProductName
|
||||
if productName == "" {
|
||||
productName = "-"
|
||||
}
|
||||
category := p.Category
|
||||
if category == "" {
|
||||
category = "-"
|
||||
}
|
||||
price := p.Price
|
||||
if price == "" {
|
||||
price = "-"
|
||||
}
|
||||
dataSource := p.DataSource
|
||||
if dataSource == "" {
|
||||
dataSource = "-"
|
||||
}
|
||||
dataSourceCode := p.DataSourceCode
|
||||
if dataSourceCode == "" {
|
||||
dataSourceCode = "-"
|
||||
}
|
||||
costPrice := p.CostPrice
|
||||
if costPrice == "" {
|
||||
costPrice = "-"
|
||||
}
|
||||
mdFile.WriteString(fmt.Sprintf("| %s | %s | %s | %s | %s | %s | %s |\n",
|
||||
p.ProductCode,
|
||||
productName,
|
||||
category,
|
||||
price,
|
||||
dataSource,
|
||||
dataSourceCode,
|
||||
costPrice))
|
||||
}
|
||||
fmt.Println("✅ Markdown 文件已保存到: processors_table.md")
|
||||
}
|
||||
}
|
||||
|
||||
// scanProcessors 扫描处理器文件
|
||||
func scanProcessors(dir string) ([]ProcessorInfo, error) {
|
||||
var processors []ProcessorInfo
|
||||
|
||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 跳过非 .go 文件
|
||||
if !strings.HasSuffix(path, "_processor.go") {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 跳过 comb 和 test 目录
|
||||
if strings.Contains(path, string(filepath.Separator)+"comb"+string(filepath.Separator)) {
|
||||
return nil
|
||||
}
|
||||
if strings.Contains(path, string(filepath.Separator)+"test"+string(filepath.Separator)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 读取文件内容
|
||||
content, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 提取产品编号(从文件名)
|
||||
filename := filepath.Base(path)
|
||||
productCode := extractProductCode(filename)
|
||||
|
||||
// 解析文件内容,提取数据源和数据源编号
|
||||
dataSource, dataSourceCode := extractDataSourceInfo(string(content))
|
||||
|
||||
processors = append(processors, ProcessorInfo{
|
||||
ProductCode: productCode,
|
||||
ProductName: "",
|
||||
Category: "",
|
||||
Price: "",
|
||||
DataSource: dataSource,
|
||||
DataSourceCode: dataSourceCode,
|
||||
CostPrice: "",
|
||||
})
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return processors, err
|
||||
}
|
||||
|
||||
// extractProductCode 从文件名提取产品编号
|
||||
func extractProductCode(filename string) string {
|
||||
// 例如: dwbg6a2c_processor.go -> DWBG6A2C
|
||||
name := strings.TrimSuffix(filename, "_processor.go")
|
||||
return strings.ToUpper(name)
|
||||
}
|
||||
|
||||
// extractDataSourceInfo 从代码中提取数据源和数据源编号
|
||||
func extractDataSourceInfo(content string) (string, string) {
|
||||
// 先尝试匹配特殊的 CallAPI 方法(如 G05HZ01CallAPI)
|
||||
specialCallAPIPattern := regexp.MustCompile(`deps\.(\w+Service)\.(\w+CallAPI)\([^,]+,\s*"([^"]+)"`)
|
||||
specialMatches := specialCallAPIPattern.FindAllStringSubmatch(content, -1)
|
||||
if len(specialMatches) > 0 {
|
||||
serviceName := specialMatches[0][1]
|
||||
dataSourceCode := specialMatches[0][3]
|
||||
return getDataSourceName(serviceName), dataSourceCode
|
||||
}
|
||||
|
||||
// 先尝试匹配 AlicloudService 的特殊情况(第一个参数是字符串路径,没有 ctx)
|
||||
// 匹配: deps.AlicloudService.CallAPI("path", ...)
|
||||
alicloudPattern := regexp.MustCompile(`deps\.AlicloudService\.CallAPI\(\s*"([^"]+)"`)
|
||||
alicloudMatches := alicloudPattern.FindAllStringSubmatch(content, -1)
|
||||
if len(alicloudMatches) > 0 {
|
||||
path := alicloudMatches[0][1]
|
||||
parts := strings.Split(path, "/")
|
||||
dataSourceCode := path
|
||||
if len(parts) > 0 {
|
||||
dataSourceCode = parts[len(parts)-1]
|
||||
}
|
||||
return "阿里云", dataSourceCode
|
||||
}
|
||||
|
||||
// 匹配普通的 CallAPI 调用
|
||||
// 匹配模式: deps.ServiceName.CallAPI(ctx, "CODE", ...) 或 deps.ServiceName.CallAPI(ctx, projectID, ...)
|
||||
callAPIPattern := regexp.MustCompile(`deps\.(\w+Service)\.CallAPI\([^,]*,\s*([^,)]+)`)
|
||||
matches := callAPIPattern.FindAllStringSubmatch(content, -1)
|
||||
|
||||
if len(matches) == 0 {
|
||||
// 检查是否有直接的 HTTP 请求(如 COMENT01)
|
||||
if strings.Contains(content, "http.NewRequest") || strings.Contains(content, "http.Client") {
|
||||
return "内部处理", ""
|
||||
}
|
||||
// 检查是否调用了其他处理器(如 QYGL3F8E)
|
||||
if strings.Contains(content, "Process") && strings.Contains(content, "Request") {
|
||||
return "内部处理", ""
|
||||
}
|
||||
return "未知", ""
|
||||
}
|
||||
|
||||
// 取第一个匹配的服务
|
||||
serviceName := matches[0][1]
|
||||
codeOrVar := strings.TrimSpace(matches[0][2])
|
||||
|
||||
var dataSourceCode string
|
||||
|
||||
// 如果是字符串字面量(带引号),直接提取
|
||||
if strings.HasPrefix(codeOrVar, `"`) && strings.HasSuffix(codeOrVar, `"`) {
|
||||
dataSourceCode = strings.Trim(codeOrVar, `"`)
|
||||
// 对于 AlicloudService,提取路径的最后部分作为数据源编号
|
||||
if serviceName == "AlicloudService" {
|
||||
parts := strings.Split(dataSourceCode, "/")
|
||||
if len(parts) > 0 {
|
||||
dataSourceCode = parts[len(parts)-1]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 如果是变量(如 projectID),尝试查找变量定义
|
||||
// 对于 XingweiService,查找 projectID 变量
|
||||
if strings.Contains(codeOrVar, "projectID") || codeOrVar == "projectID" {
|
||||
projectIDPattern := regexp.MustCompile(`projectID\s*:=\s*"([^"]+)"`)
|
||||
projectIDMatches := projectIDPattern.FindAllStringSubmatch(content, -1)
|
||||
if len(projectIDMatches) > 0 {
|
||||
// 取最后一个匹配的 projectID(通常是最接近 CallAPI 的那个)
|
||||
dataSourceCode = projectIDMatches[len(projectIDMatches)-1][1]
|
||||
} else {
|
||||
dataSourceCode = "变量未找到"
|
||||
}
|
||||
} else {
|
||||
// 尝试查找变量定义(通用模式)
|
||||
varPattern := regexp.MustCompile(regexp.QuoteMeta(codeOrVar) + `\s*:=\s*"([^"]+)"`)
|
||||
varMatches := varPattern.FindAllStringSubmatch(content, -1)
|
||||
if len(varMatches) > 0 {
|
||||
dataSourceCode = varMatches[len(varMatches)-1][1]
|
||||
} else {
|
||||
dataSourceCode = codeOrVar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 根据服务名确定数据源
|
||||
dataSource := getDataSourceName(serviceName)
|
||||
|
||||
return dataSource, dataSourceCode
|
||||
}
|
||||
|
||||
// getDataSourceName 根据服务名获取数据源名称
|
||||
func getDataSourceName(serviceName string) string {
|
||||
switch serviceName {
|
||||
case "ZhichaService":
|
||||
return "安徽智查"
|
||||
case "YushanService":
|
||||
return "羽山数据"
|
||||
case "WestDexService":
|
||||
return "西部数据"
|
||||
case "XingweiService":
|
||||
return "四川星维"
|
||||
case "TianYanChaService":
|
||||
return "天眼查"
|
||||
case "AlicloudService":
|
||||
return "阿里云"
|
||||
case "MuziService":
|
||||
return "木子数据"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
// 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.Silent), // 禁用日志输出,减少噪音
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// checkProductAndProcessorCounts 检查数据库产品数量和处理器数量
|
||||
func checkProductAndProcessorCounts(ctx context.Context, db *gorm.DB, processors []ProcessorInfo) {
|
||||
// 统计处理器数量(排除 comb)
|
||||
processorCount := len(processors)
|
||||
fmt.Printf("\n=== 统计信息 ===\n")
|
||||
fmt.Printf("处理器数量(排除 comb): %d\n", processorCount)
|
||||
|
||||
// 统计数据库中的产品数量(排除组合包)
|
||||
var productCount int64
|
||||
// 先尝试单数表名
|
||||
err := db.WithContext(ctx).
|
||||
Table("product").
|
||||
Where("is_package = ? AND deleted_at IS NULL", false).
|
||||
Count(&productCount).Error
|
||||
|
||||
// 如果单数表名查询失败,尝试复数表名
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "does not exist") {
|
||||
err = db.WithContext(ctx).
|
||||
Table("products").
|
||||
Where("is_package = ? AND deleted_at IS NULL", false).
|
||||
Count(&productCount).Error
|
||||
}
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
fmt.Printf("数据库产品数量(排除组合包): %d\n", productCount)
|
||||
} else {
|
||||
fmt.Printf("数据库产品数量查询失败: %v\n", err)
|
||||
}
|
||||
|
||||
// 统计有匹配产品的处理器数量
|
||||
matchedCount := 0
|
||||
for _, p := range processors {
|
||||
var count int64
|
||||
err := db.WithContext(ctx).
|
||||
Table("product").
|
||||
Where("code = ? AND deleted_at IS NULL", p.ProductCode).
|
||||
Count(&count).Error
|
||||
|
||||
if err != nil && strings.Contains(err.Error(), "does not exist") {
|
||||
err = db.WithContext(ctx).
|
||||
Table("products").
|
||||
Where("code = ? AND deleted_at IS NULL", p.ProductCode).
|
||||
Count(&count).Error
|
||||
}
|
||||
|
||||
if err == nil && count > 0 {
|
||||
matchedCount++
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("有匹配产品的处理器数量: %d/%d\n", matchedCount, processorCount)
|
||||
fmt.Printf("无匹配产品的处理器数量: %d/%d\n", processorCount-matchedCount, processorCount)
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// queryProduct 查询产品信息
|
||||
func queryProduct(ctx context.Context, db *gorm.DB, code string) (*Product, error) {
|
||||
var product Product
|
||||
var err error
|
||||
|
||||
// 尝试不同的表名查询(先尝试单数表名,因为用户确认表名是 product)
|
||||
tableNames := []string{"product", "products"}
|
||||
for _, tableName := range tableNames {
|
||||
err = db.WithContext(ctx).
|
||||
Table(tableName).
|
||||
Select("code, name, category_id, price").
|
||||
Where("code = ? AND deleted_at IS NULL", code).
|
||||
First(&product).Error
|
||||
|
||||
if err == nil {
|
||||
// 查询成功,查询分类信息
|
||||
if product.CategoryID != "" {
|
||||
var category ProductCategory
|
||||
// 尝试不同的分类表名(先尝试单数表名)
|
||||
categoryTableNames := []string{"product_category", "product_categories"}
|
||||
for _, catTableName := range categoryTableNames {
|
||||
err = db.WithContext(ctx).
|
||||
Table(catTableName).
|
||||
Select("id, name").
|
||||
Where("id = ? AND deleted_at IS NULL", product.CategoryID).
|
||||
First(&category).Error
|
||||
if err == nil {
|
||||
product.Category = &category
|
||||
break
|
||||
}
|
||||
// 如果是表不存在的错误,继续尝试下一个表名
|
||||
if err != nil && strings.Contains(err.Error(), "does not exist") {
|
||||
continue
|
||||
}
|
||||
// 如果是记录不存在的错误,也继续尝试(可能是表名不对)
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
continue
|
||||
}
|
||||
}
|
||||
// 即使分类查询失败,也返回产品信息(分类可以为空)
|
||||
}
|
||||
return &product, nil
|
||||
}
|
||||
|
||||
// 检查错误类型
|
||||
errStr := err.Error()
|
||||
// 如果是表不存在的错误,继续尝试下一个表名
|
||||
if strings.Contains(errStr, "does not exist") {
|
||||
continue
|
||||
}
|
||||
// 如果是记录不存在的错误,也继续尝试(可能是表名不对)
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
continue
|
||||
}
|
||||
// 其他错误直接返回
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 所有表名都查询失败
|
||||
return nil, gorm.ErrRecordNotFound
|
||||
}
|
||||
|
||||
// printTable 打印表格
|
||||
func printTable(processors []ProcessorInfo) {
|
||||
// 打印表头
|
||||
fmt.Printf("%-15s %-30s %-20s %-15s %-15s %-20s %-15s\n",
|
||||
"产品编号", "产品名称", "分类", "价格", "数据源", "数据源编号", "成本价")
|
||||
fmt.Println(strings.Repeat("-", 130))
|
||||
|
||||
// 打印数据
|
||||
for _, p := range processors {
|
||||
fmt.Printf("%-15s %-30s %-20s %-15s %-15s %-20s %-15s\n",
|
||||
p.ProductCode,
|
||||
p.ProductName,
|
||||
p.Category,
|
||||
p.Price,
|
||||
p.DataSource,
|
||||
p.DataSourceCode,
|
||||
p.CostPrice)
|
||||
}
|
||||
|
||||
// 打印 CSV 格式
|
||||
fmt.Println("\n=== CSV 格式 ===")
|
||||
fmt.Println("产品编号,产品名称,分类,价格,数据源,数据源编号,成本价")
|
||||
for _, p := range processors {
|
||||
// 转义 CSV 中的特殊字符
|
||||
productName := strings.ReplaceAll(p.ProductName, ",", ",")
|
||||
category := strings.ReplaceAll(p.Category, ",", ",")
|
||||
fmt.Printf("%s,%s,%s,%s,%s,%s,%s\n",
|
||||
p.ProductCode,
|
||||
productName,
|
||||
category,
|
||||
p.Price,
|
||||
p.DataSource,
|
||||
p.DataSourceCode,
|
||||
p.CostPrice)
|
||||
}
|
||||
|
||||
// 打印 Markdown 表格格式
|
||||
fmt.Println("\n=== Markdown 表格格式 ===")
|
||||
fmt.Println("| 产品编号 | 产品名称 | 分类 | 价格 | 数据源 | 数据源编号 | 成本价 |")
|
||||
fmt.Println("|---------|---------|------|------|--------|-----------|--------|")
|
||||
for _, p := range processors {
|
||||
productName := p.ProductName
|
||||
if productName == "" {
|
||||
productName = "-"
|
||||
}
|
||||
category := p.Category
|
||||
if category == "" {
|
||||
category = "-"
|
||||
}
|
||||
price := p.Price
|
||||
if price == "" {
|
||||
price = "-"
|
||||
}
|
||||
dataSource := p.DataSource
|
||||
if dataSource == "" {
|
||||
dataSource = "-"
|
||||
}
|
||||
dataSourceCode := p.DataSourceCode
|
||||
if dataSourceCode == "" {
|
||||
dataSourceCode = "-"
|
||||
}
|
||||
costPrice := p.CostPrice
|
||||
if costPrice == "" {
|
||||
costPrice = "-"
|
||||
}
|
||||
fmt.Printf("| %s | %s | %s | %s | %s | %s | %s |\n",
|
||||
p.ProductCode,
|
||||
productName,
|
||||
category,
|
||||
price,
|
||||
dataSource,
|
||||
dataSourceCode,
|
||||
costPrice)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user