package tables import ( "encoding/json" "fmt" "git.x2erp.com/qdy/go-base/logger" "git.x2erp.com/qdy/go-db/factory/database" ) // 默认值函数类型 type DefaultValueFunc func(*database.DBFactory) error // 默认值注册表 var defaultValueRegistrations []DefaultValueFunc // RegisterDefaultValues 注册默认值函数 func RegisterDefaultValues(fn DefaultValueFunc) { defaultValueRegistrations = append(defaultValueRegistrations, fn) } // RegisterAllDefaults 注册所有默认值 func RegisterAllDefaults(dbFactory *database.DBFactory) error { if dbFactory == nil { return fmt.Errorf("数据库工厂为空") } for _, fn := range defaultValueRegistrations { if err := fn(dbFactory); err != nil { return err } } logger.Info("所有默认值注册完成") return nil } // init 注册内置的默认值函数 func init() { RegisterDefaultValues(registerStoreDimensionDefaults) RegisterDefaultValues(registerProductDimensionDefaults) RegisterDefaultValues(registerCompanyDimensionDefaults) } // 注册维度表默认值(兼容旧版本) func RegisterDimensionDefaults(dbFactory *database.DBFactory) error { return RegisterAllDefaults(dbFactory) } // 注册店铺维度默认值 func registerStoreDimensionDefaults(dbFactory *database.DBFactory) error { dimensions := []MasterStoreDimension{ // 维度1: 经营权模式 (Business Model) { ID: generateID("business_model", "DIR"), Type: "business_model", Code: "DIR", Name: "直营店", Description: "品牌方全资拥有,完全控制", SortOrder: 1, }, { ID: generateID("business_model", "FRC"), Type: "business_model", Code: "FRC", Name: "特许加盟店", Description: "加盟商投资,品牌授权经营", SortOrder: 2, }, { ID: generateID("business_model", "DSP"), Type: "business_model", Code: "DSP", Name: "经销商店", Description: "区域买断式经销", SortOrder: 3, }, { ID: generateID("business_model", "CON"), Type: "business_model", Code: "CON", Name: "联营店/寄售店", Description: "品牌供货,联营方提供场地和人员", SortOrder: 4, }, { ID: generateID("business_model", "WHL"), Type: "business_model", Code: "WHL", Name: "批发客户", Description: "B2B批发,无零售店面", SortOrder: 5, }, { ID: generateID("business_model", "COR"), Type: "business_model", Code: "COR", Name: "公司内购店", Description: "企业内部销售点", SortOrder: 6, }, // 维度2: 店铺定位 (Store Tier) { ID: generateID("store_tier", "FLA"), Type: "store_tier", Code: "FLA", Name: "旗舰店", Description: "核心商圈,全品类,品牌形象展示", SortOrder: 1, ExtraProperties: toJSON(map[string]interface{}{ "min_area": 200.0, "max_area": 500.0, }), }, { ID: generateID("store_tier", "IMG"), Type: "store_tier", Code: "IMG", Name: "形象店", Description: "主要商圈,完整品类,标准形象", SortOrder: 2, ExtraProperties: toJSON(map[string]interface{}{ "min_area": 120.0, "max_area": 250.0, }), }, { ID: generateID("store_tier", "PRI"), Type: "store_tier", Code: "PRI", Name: "主力店", Description: "区域中心,全系列产品", SortOrder: 3, ExtraProperties: toJSON(map[string]interface{}{ "min_area": 80.0, "max_area": 150.0, }), }, { ID: generateID("store_tier", "SEC"), Type: "store_tier", Code: "SEC", Name: "标准店", Description: "社区/二级商圈,主打系列", SortOrder: 4, ExtraProperties: toJSON(map[string]interface{}{ "min_area": 50.0, "max_area": 100.0, }), }, { ID: generateID("store_tier", "OUT"), Type: "store_tier", Code: "OUT", Name: "奥莱店", Description: "奥特莱斯商圈,过季品/特供品", SortOrder: 5, ExtraProperties: toJSON(map[string]interface{}{ "min_area": 100.0, "max_area": 300.0, }), }, { ID: generateID("store_tier", "POP"), Type: "store_tier", Code: "POP", Name: "快闪店", Description: "临时性,营销活动驱动", SortOrder: 6, ExtraProperties: toJSON(map[string]interface{}{ "min_area": 30.0, "max_area": 80.0, "temporary": true, }), }, // 维度3: 零售业态 (Retail Format) { ID: generateID("retail_format", "FSS"), Type: "retail_format", Code: "FSS", Name: "独立街铺", Description: "临街独立店面", SortOrder: 1, ExtraProperties: toJSON(map[string]interface{}{ "business_hours_type": "STREET", }), }, { ID: generateID("retail_format", "DPM"), Type: "retail_format", Code: "DPM", Name: "百货专柜", Description: "百货公司内专柜", SortOrder: 2, ExtraProperties: toJSON(map[string]interface{}{ "business_hours_type": "DEPARTMENT_STORE", }), }, { ID: generateID("retail_format", "SMC"), Type: "retail_format", Code: "SMC", Name: "购物中心店", Description: "购物中心内店铺", SortOrder: 3, ExtraProperties: toJSON(map[string]interface{}{ "business_hours_type": "MALL", }), }, { ID: generateID("retail_format", "AIR"), Type: "retail_format", Code: "AIR", Name: "机场店", Description: "机场航站楼内", SortOrder: 4, ExtraProperties: toJSON(map[string]interface{}{ "business_hours_type": "AIRPORT", }), }, { ID: generateID("retail_format", "TRS"), Type: "retail_format", Code: "TRS", Name: "交通枢纽店", Description: "高铁站/地铁站内", SortOrder: 5, ExtraProperties: toJSON(map[string]interface{}{ "business_hours_type": "TRANSPORT_HUB", }), }, { ID: generateID("retail_format", "RES"), Type: "retail_format", Code: "RES", Name: "度假区店", Description: "旅游度假区内", SortOrder: 6, ExtraProperties: toJSON(map[string]interface{}{ "business_hours_type": "RESORT", }), }, { ID: generateID("retail_format", "HOS"), Type: "retail_format", Code: "HOS", Name: "酒店店", Description: "高端酒店内", SortOrder: 7, ExtraProperties: toJSON(map[string]interface{}{ "business_hours_type": "HOTEL", }), }, // 维度4: 市场层级 (Market Tier) { ID: generateID("market_tier", "T0"), Type: "market_tier", Code: "T0", Name: "超一线城市", Description: "纽约、伦敦、东京、上海、北京", SortOrder: 1, }, { ID: generateID("market_tier", "T1"), Type: "market_tier", Code: "T1", Name: "一线城市", Description: "深圳、广州、巴黎、米兰", SortOrder: 2, }, { ID: generateID("market_tier", "T2"), Type: "market_tier", Code: "T2", Name: "二线城市", Description: "成都、杭州、南京", SortOrder: 3, }, { ID: generateID("market_tier", "T3"), Type: "market_tier", Code: "T3", Name: "三线城市", Description: "无锡、宁波、佛山", SortOrder: 4, }, { ID: generateID("market_tier", "T4"), Type: "market_tier", Code: "T4", Name: "四线及以下", Description: "其他地级市及县城", SortOrder: 5, }, // 维度5: 销售模式 (Sales Channel) { ID: generateID("sales_channel", "OFF"), Type: "sales_channel", Code: "OFF", Name: "线下实体", Description: "所有实体店铺", SortOrder: 1, }, { ID: generateID("sales_channel", "ECC"), Type: "sales_channel", Code: "ECC", Name: "平台电商", Description: "天猫、京东、亚马逊", SortOrder: 2, }, { ID: generateID("sales_channel", "DTC"), Type: "sales_channel", Code: "DTC", Name: "品牌直营电商", Description: "官网、官方APP", SortOrder: 3, }, { ID: generateID("sales_channel", "SOC"), Type: "sales_channel", Code: "SOC", Name: "社交电商", Description: "抖音、小红书、Instagram", SortOrder: 4, }, { ID: generateID("sales_channel", "LEC"), Type: "sales_channel", Code: "LEC", Name: "直播电商", Description: "淘宝直播、抖音直播", SortOrder: 5, }, // 区域维度 (Region) - 示例数据,实际应该从业务系统同步 { ID: generateID("region", "CN"), Type: "region", Code: "CN", Name: "中国", Description: "中华人民共和国", SortOrder: 1, ExtraProperties: toJSON(map[string]interface{}{ "level": 1, }), }, { ID: generateID("region", "CN-BJ"), Type: "region", Code: "BJ", Name: "北京", Description: "北京市", SortOrder: 2, ExtraProperties: toJSON(map[string]interface{}{ "parent_id": generateID("region", "CN"), "level": 3, }), }, { ID: generateID("region", "CN-SH"), Type: "region", Code: "SH", Name: "上海", Description: "上海市", SortOrder: 3, ExtraProperties: toJSON(map[string]interface{}{ "parent_id": generateID("region", "CN"), "level": 3, }), }, } // 批量插入数据 for _, dim := range dimensions { if err := insertOrUpdateStoreDimension(dbFactory, dim); err != nil { logger.Warn("插入店铺维度数据失败: type=%s, code=%s, error=%v", dim.Type, dim.Code, err) // 继续插入其他数据 } } logger.Info("店铺维度默认值注册完成,共 %d 条记录", len(dimensions)) return nil } // 注册商品维度默认值 func registerProductDimensionDefaults(dbFactory *database.DBFactory) error { // 商品维度示例数据 dimensions := []MasterProductDimension{ // 商品大类示例 { ID: generateID("category_major", "CLOTHING"), Type: "category_major", Code: "CLOTHING", Name: "服装", Description: "服装类商品", SortOrder: 1, }, { ID: generateID("category_major", "SHOES"), Type: "category_major", Code: "SHOES", Name: "鞋类", Description: "鞋类商品", SortOrder: 2, }, { ID: generateID("category_major", "ACCESSORIES"), Type: "category_major", Code: "ACCESSORIES", Name: "配饰", Description: "配饰类商品", SortOrder: 3, }, // 季节示例 { ID: generateID("season", "SS"), Type: "season", Code: "SS", Name: "春夏", Description: "春季和夏季", SortOrder: 1, }, { ID: generateID("season", "FW"), Type: "season", Code: "FW", Name: "秋冬", Description: "秋季和冬季", SortOrder: 2, }, // 波段示例 { ID: generateID("wave", "W1"), Type: "wave", Code: "W1", Name: "第一波段", Description: "第一波段商品", SortOrder: 1, }, { ID: generateID("wave", "W2"), Type: "wave", Code: "W2", Name: "第二波段", Description: "第二波段商品", SortOrder: 2, }, // 面料示例 { ID: generateID("fabric", "COTTON"), Type: "fabric", Code: "COTTON", Name: "棉", Description: "棉质面料", SortOrder: 1, }, { ID: generateID("fabric", "POLYESTER"), Type: "fabric", Code: "POLYESTER", Name: "涤纶", Description: "涤纶面料", SortOrder: 2, }, { ID: generateID("fabric", "WOOL"), Type: "fabric", Code: "WOOL", Name: "羊毛", Description: "羊毛面料", SortOrder: 3, }, // 颜色色系示例 { ID: generateID("color_family", "RED"), Type: "color_family", Code: "RED", Name: "红色系", Description: "红色系列", SortOrder: 1, }, { ID: generateID("color_family", "BLUE"), Type: "color_family", Code: "BLUE", Name: "蓝色系", Description: "蓝色系列", SortOrder: 2, }, { ID: generateID("color_family", "BLACK"), Type: "color_family", Code: "BLACK", Name: "黑色系", Description: "黑色系列", SortOrder: 3, }, // 尺码组示例 { ID: generateID("size_group", "XS-S"), Type: "size_group", Code: "XS-S", Name: "超小-小号", Description: "超小号到小号", SortOrder: 1, }, { ID: generateID("size_group", "M-L"), Type: "size_group", Code: "M-L", Name: "中号-大号", Description: "中号到大号", SortOrder: 2, }, { ID: generateID("size_group", "XL-XXL"), Type: "size_group", Code: "XL-XXL", Name: "加大-特大号", Description: "加大号到特大号", SortOrder: 3, }, } // 批量插入数据 for _, dim := range dimensions { if err := insertOrUpdateProductDimension(dbFactory, dim); err != nil { logger.Warn("插入商品维度数据失败: type=%s, code=%s, error=%v", dim.Type, dim.Code, err) // 继续插入其他数据 } } logger.Info("商品维度默认值注册完成,共 %d 条记录", len(dimensions)) return nil } // 插入或更新店铺维度数据 func insertOrUpdateStoreDimension(dbFactory *database.DBFactory, dim MasterStoreDimension) error { db := dbFactory.GetDB() if db == nil { return fmt.Errorf("数据库连接为空") } // 使用ON DUPLICATE KEY UPDATE逻辑 // 注意:这里假设使用MySQL方言 query := `INSERT INTO master_store_dimension (id, type, code, name, description, sort_order, extra_properties, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, NOW(), NOW()) ON DUPLICATE KEY UPDATE name = VALUES(name), description = VALUES(description), sort_order = VALUES(sort_order), extra_properties = VALUES(extra_properties), updated_at = NOW()` _, err := db.Exec(query, dim.ID, dim.Type, dim.Code, dim.Name, dim.Description, dim.SortOrder, dim.ExtraProperties) return err } // 插入或更新商品维度数据 func insertOrUpdateProductDimension(dbFactory *database.DBFactory, dim MasterProductDimension) error { db := dbFactory.GetDB() if db == nil { return fmt.Errorf("数据库连接为空") } query := `INSERT INTO master_product_dimension (id, type, code, name, description, sort_order, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, NOW(), NOW()) ON DUPLICATE KEY UPDATE name = VALUES(name), description = VALUES(description), sort_order = VALUES(sort_order), updated_at = NOW()` _, err := db.Exec(query, dim.ID, dim.Type, dim.Code, dim.Name, dim.Description, dim.SortOrder) return err } // 生成ID func generateID(dimType, code string) string { return fmt.Sprintf("%s_%s", dimType, code) } // 转换为JSON字符串 func toJSON(data map[string]interface{}) string { if data == nil { return "{}" } jsonBytes, err := json.Marshal(data) if err != nil { return "{}" } return string(jsonBytes) } // ============================ // 默认值注册使用示例 // ============================ // 示例:为主数据表注册默认值(如果需要) // func registerProductDefaults(dbFactory *database.DBFactory) error { // // 示例:插入一些默认的商品分类数据 // // 注意:实际应用中,主数据通常从ERP系统同步,不需要默认值 // return nil // } // // 在包的init()函数中注册: // func init() { // RegisterDefaultValues(registerProductDefaults) // } // 注意:要为其他表添加默认值,请遵循以下步骤: // 1. 在任意表文件中定义一个函数:func myTableDefaults(dbFactory *database.DBFactory) error // 2. 在函数的init()中调用RegisterDefaultValues注册该函数 // 3. 确保函数在包初始化时被注册(init()函数会自动执行) // 4. 在应用启动时调用tables.RegisterAllDefaults(dbFactory)执行所有注册 // 注册公司维度默认值 func registerCompanyDimensionDefaults(dbFactory *database.DBFactory) error { if dbFactory == nil { return fmt.Errorf("数据库工厂为空") } dimensions := []MasterCompanyDimension{ // 公司类型维度 { ID: generateID("company_type", "SUPPLIER"), Type: "company_type", Code: "SUPPLIER", Name: "供应商", Description: "商品供应商,提供采购商品", SortOrder: 1, }, { ID: generateID("company_type", "SUBSIDIARY"), Type: "company_type", Code: "SUBSIDIARY", Name: "子公司", Description: "集团下属子公司", SortOrder: 2, }, { ID: generateID("company_type", "AGENT"), Type: "company_type", Code: "AGENT", Name: "代理商", Description: "品牌代理商,负责区域销售", SortOrder: 3, }, { ID: generateID("company_type", "WHOLESALER"), Type: "company_type", Code: "WHOLESALER", Name: "批发商", Description: "批发销售商,批量采购销售", SortOrder: 4, }, { ID: generateID("company_type", "GROUP"), Type: "company_type", Code: "GROUP", Name: "集团", Description: "集团公司总部", SortOrder: 5, }, { ID: generateID("company_type", "FRANCHISEE"), Type: "company_type", Code: "FRANCHISEE", Name: "加盟商", Description: "品牌加盟商", SortOrder: 6, }, { ID: generateID("company_type", "CUSTOMER"), Type: "company_type", Code: "CUSTOMER", Name: "客户", Description: "终端客户", SortOrder: 7, }, { ID: generateID("company_type", "LOGISTICS"), Type: "company_type", Code: "LOGISTICS", Name: "物流商", Description: "物流运输服务商", SortOrder: 8, }, } for _, dimension := range dimensions { query := `INSERT INTO master_company_dimension (id, type, code, name, description, sort_order, extra_properties, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, NOW(), NOW()) ON DUPLICATE KEY UPDATE name = VALUES(name), description = VALUES(description), sort_order = VALUES(sort_order), extra_properties = VALUES(extra_properties), updated_at = NOW()` if _, err := dbFactory.GetDB().Exec(query, dimension.ID, dimension.Type, dimension.Code, dimension.Name, dimension.Description, dimension.SortOrder, dimension.ExtraProperties, ); err != nil { return fmt.Errorf("插入公司维度数据失败: %v", err) } } logger.Info("公司维度默认值注册完成") return nil }