Нет описания
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

init_defaults.go 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. package tables
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "git.x2erp.com/qdy/go-base/logger"
  6. "git.x2erp.com/qdy/go-db/factory/database"
  7. )
  8. // 默认值函数类型
  9. type DefaultValueFunc func(*database.DBFactory) error
  10. // 默认值注册表
  11. var defaultValueRegistrations []DefaultValueFunc
  12. // RegisterDefaultValues 注册默认值函数
  13. func RegisterDefaultValues(fn DefaultValueFunc) {
  14. defaultValueRegistrations = append(defaultValueRegistrations, fn)
  15. }
  16. // RegisterAllDefaults 注册所有默认值
  17. func RegisterAllDefaults(dbFactory *database.DBFactory) error {
  18. if dbFactory == nil {
  19. return fmt.Errorf("数据库工厂为空")
  20. }
  21. for _, fn := range defaultValueRegistrations {
  22. if err := fn(dbFactory); err != nil {
  23. return err
  24. }
  25. }
  26. logger.Info("所有默认值注册完成")
  27. return nil
  28. }
  29. // init 注册内置的默认值函数
  30. func init() {
  31. RegisterDefaultValues(registerStoreDimensionDefaults)
  32. RegisterDefaultValues(registerProductDimensionDefaults)
  33. RegisterDefaultValues(registerCompanyDimensionDefaults)
  34. }
  35. // 注册维度表默认值(兼容旧版本)
  36. func RegisterDimensionDefaults(dbFactory *database.DBFactory) error {
  37. return RegisterAllDefaults(dbFactory)
  38. }
  39. // 注册店铺维度默认值
  40. func registerStoreDimensionDefaults(dbFactory *database.DBFactory) error {
  41. dimensions := []MasterStoreDimension{
  42. // 维度1: 经营权模式 (Business Model)
  43. {
  44. ID: generateID("business_model", "DIR"),
  45. Type: "business_model",
  46. Code: "DIR",
  47. Name: "直营店",
  48. Description: "品牌方全资拥有,完全控制",
  49. SortOrder: 1,
  50. },
  51. {
  52. ID: generateID("business_model", "FRC"),
  53. Type: "business_model",
  54. Code: "FRC",
  55. Name: "特许加盟店",
  56. Description: "加盟商投资,品牌授权经营",
  57. SortOrder: 2,
  58. },
  59. {
  60. ID: generateID("business_model", "DSP"),
  61. Type: "business_model",
  62. Code: "DSP",
  63. Name: "经销商店",
  64. Description: "区域买断式经销",
  65. SortOrder: 3,
  66. },
  67. {
  68. ID: generateID("business_model", "CON"),
  69. Type: "business_model",
  70. Code: "CON",
  71. Name: "联营店/寄售店",
  72. Description: "品牌供货,联营方提供场地和人员",
  73. SortOrder: 4,
  74. },
  75. {
  76. ID: generateID("business_model", "WHL"),
  77. Type: "business_model",
  78. Code: "WHL",
  79. Name: "批发客户",
  80. Description: "B2B批发,无零售店面",
  81. SortOrder: 5,
  82. },
  83. {
  84. ID: generateID("business_model", "COR"),
  85. Type: "business_model",
  86. Code: "COR",
  87. Name: "公司内购店",
  88. Description: "企业内部销售点",
  89. SortOrder: 6,
  90. },
  91. // 维度2: 店铺定位 (Store Tier)
  92. {
  93. ID: generateID("store_tier", "FLA"),
  94. Type: "store_tier",
  95. Code: "FLA",
  96. Name: "旗舰店",
  97. Description: "核心商圈,全品类,品牌形象展示",
  98. SortOrder: 1,
  99. },
  100. {
  101. ID: generateID("store_tier", "IMG"),
  102. Type: "store_tier",
  103. Code: "IMG",
  104. Name: "形象店",
  105. Description: "主要商圈,完整品类,标准形象",
  106. SortOrder: 2,
  107. },
  108. {
  109. ID: generateID("store_tier", "PRI"),
  110. Type: "store_tier",
  111. Code: "PRI",
  112. Name: "主力店",
  113. Description: "区域中心,全系列产品",
  114. SortOrder: 3,
  115. },
  116. {
  117. ID: generateID("store_tier", "SEC"),
  118. Type: "store_tier",
  119. Code: "SEC",
  120. Name: "标准店",
  121. Description: "社区/二级商圈,主打系列",
  122. SortOrder: 4,
  123. },
  124. {
  125. ID: generateID("store_tier", "OUT"),
  126. Type: "store_tier",
  127. Code: "OUT",
  128. Name: "奥莱店",
  129. Description: "奥特莱斯商圈,过季品/特供品",
  130. SortOrder: 5,
  131. },
  132. {
  133. ID: generateID("store_tier", "POP"),
  134. Type: "store_tier",
  135. Code: "POP",
  136. Name: "快闪店",
  137. Description: "临时性,营销活动驱动",
  138. SortOrder: 6,
  139. },
  140. // 维度3: 零售业态 (Retail Format)
  141. {
  142. ID: generateID("retail_format", "FSS"),
  143. Type: "retail_format",
  144. Code: "FSS",
  145. Name: "独立街铺",
  146. Description: "临街独立店面",
  147. SortOrder: 1,
  148. },
  149. {
  150. ID: generateID("retail_format", "DPM"),
  151. Type: "retail_format",
  152. Code: "DPM",
  153. Name: "百货专柜",
  154. Description: "百货公司内专柜",
  155. SortOrder: 2,
  156. },
  157. {
  158. ID: generateID("retail_format", "SMC"),
  159. Type: "retail_format",
  160. Code: "SMC",
  161. Name: "购物中心店",
  162. Description: "购物中心内店铺",
  163. SortOrder: 3,
  164. },
  165. {
  166. ID: generateID("retail_format", "AIR"),
  167. Type: "retail_format",
  168. Code: "AIR",
  169. Name: "机场店",
  170. Description: "机场航站楼内",
  171. SortOrder: 4,
  172. },
  173. {
  174. ID: generateID("retail_format", "TRS"),
  175. Type: "retail_format",
  176. Code: "TRS",
  177. Name: "交通枢纽店",
  178. Description: "高铁站/地铁站内",
  179. SortOrder: 5,
  180. },
  181. {
  182. ID: generateID("retail_format", "RES"),
  183. Type: "retail_format",
  184. Code: "RES",
  185. Name: "度假区店",
  186. Description: "旅游度假区内",
  187. SortOrder: 6,
  188. },
  189. {
  190. ID: generateID("retail_format", "HOS"),
  191. Type: "retail_format",
  192. Code: "HOS",
  193. Name: "酒店店",
  194. Description: "高端酒店内",
  195. SortOrder: 7,
  196. },
  197. // 维度4: 市场层级 (Market Tier)
  198. {
  199. ID: generateID("market_tier", "T0"),
  200. Type: "market_tier",
  201. Code: "T0",
  202. Name: "超一线城市",
  203. Description: "纽约、伦敦、东京、上海、北京",
  204. SortOrder: 1,
  205. },
  206. {
  207. ID: generateID("market_tier", "T1"),
  208. Type: "market_tier",
  209. Code: "T1",
  210. Name: "一线城市",
  211. Description: "深圳、广州、巴黎、米兰",
  212. SortOrder: 2,
  213. },
  214. {
  215. ID: generateID("market_tier", "T2"),
  216. Type: "market_tier",
  217. Code: "T2",
  218. Name: "二线城市",
  219. Description: "成都、杭州、南京",
  220. SortOrder: 3,
  221. },
  222. {
  223. ID: generateID("market_tier", "T3"),
  224. Type: "market_tier",
  225. Code: "T3",
  226. Name: "三线城市",
  227. Description: "无锡、宁波、佛山",
  228. SortOrder: 4,
  229. },
  230. {
  231. ID: generateID("market_tier", "T4"),
  232. Type: "market_tier",
  233. Code: "T4",
  234. Name: "四线及以下",
  235. Description: "其他地级市及县城",
  236. SortOrder: 5,
  237. },
  238. // 维度5: 销售模式 (Sales Channel)
  239. {
  240. ID: generateID("sales_channel", "OFF"),
  241. Type: "sales_channel",
  242. Code: "OFF",
  243. Name: "线下实体",
  244. Description: "所有实体店铺",
  245. SortOrder: 1,
  246. },
  247. {
  248. ID: generateID("sales_channel", "ECC"),
  249. Type: "sales_channel",
  250. Code: "ECC",
  251. Name: "平台电商",
  252. Description: "天猫、京东、亚马逊",
  253. SortOrder: 2,
  254. },
  255. {
  256. ID: generateID("sales_channel", "DTC"),
  257. Type: "sales_channel",
  258. Code: "DTC",
  259. Name: "品牌直营电商",
  260. Description: "官网、官方APP",
  261. SortOrder: 3,
  262. },
  263. {
  264. ID: generateID("sales_channel", "SOC"),
  265. Type: "sales_channel",
  266. Code: "SOC",
  267. Name: "社交电商",
  268. Description: "抖音、小红书、Instagram",
  269. SortOrder: 4,
  270. },
  271. {
  272. ID: generateID("sales_channel", "LEC"),
  273. Type: "sales_channel",
  274. Code: "LEC",
  275. Name: "直播电商",
  276. Description: "淘宝直播、抖音直播",
  277. SortOrder: 5,
  278. },
  279. // 区域维度 (Region) - 示例数据,实际应该从业务系统同步
  280. {
  281. ID: generateID("region", "CN"),
  282. Type: "region",
  283. Code: "CN",
  284. Name: "中国",
  285. Description: "中华人民共和国",
  286. SortOrder: 1,
  287. },
  288. {
  289. ID: generateID("region", "CN-BJ"),
  290. Type: "region",
  291. Code: "BJ",
  292. Name: "北京",
  293. Description: "北京市",
  294. SortOrder: 2,
  295. },
  296. {
  297. ID: generateID("region", "CN-SH"),
  298. Type: "region",
  299. Code: "SH",
  300. Name: "上海",
  301. Description: "上海市",
  302. SortOrder: 3,
  303. },
  304. }
  305. // 批量插入数据
  306. for _, dim := range dimensions {
  307. if err := insertOrUpdateStoreDimension(dbFactory, dim); err != nil {
  308. logger.Warn("插入店铺维度数据失败: type=%s, code=%s, error=%v", dim.Type, dim.Code, err)
  309. // 继续插入其他数据
  310. }
  311. }
  312. logger.Info("店铺维度默认值注册完成,共 %d 条记录", len(dimensions))
  313. return nil
  314. }
  315. // 注册商品维度默认值
  316. func registerProductDimensionDefaults(dbFactory *database.DBFactory) error {
  317. // 商品维度示例数据
  318. dimensions := []MasterProductDimension{
  319. // 商品大类示例
  320. {
  321. ID: generateID("category_major", "CLOTHING"),
  322. Type: "category_major",
  323. Code: "CLOTHING",
  324. Name: "服装",
  325. Description: "服装类商品",
  326. SortOrder: 1,
  327. },
  328. {
  329. ID: generateID("category_major", "SHOES"),
  330. Type: "category_major",
  331. Code: "SHOES",
  332. Name: "鞋类",
  333. Description: "鞋类商品",
  334. SortOrder: 2,
  335. },
  336. {
  337. ID: generateID("category_major", "ACCESSORIES"),
  338. Type: "category_major",
  339. Code: "ACCESSORIES",
  340. Name: "配饰",
  341. Description: "配饰类商品",
  342. SortOrder: 3,
  343. },
  344. // 季节示例
  345. {
  346. ID: generateID("season", "SS"),
  347. Type: "season",
  348. Code: "SS",
  349. Name: "春夏",
  350. Description: "春季和夏季",
  351. SortOrder: 1,
  352. },
  353. {
  354. ID: generateID("season", "FW"),
  355. Type: "season",
  356. Code: "FW",
  357. Name: "秋冬",
  358. Description: "秋季和冬季",
  359. SortOrder: 2,
  360. },
  361. // 波段示例
  362. {
  363. ID: generateID("wave", "W1"),
  364. Type: "wave",
  365. Code: "W1",
  366. Name: "第一波段",
  367. Description: "第一波段商品",
  368. SortOrder: 1,
  369. },
  370. {
  371. ID: generateID("wave", "W2"),
  372. Type: "wave",
  373. Code: "W2",
  374. Name: "第二波段",
  375. Description: "第二波段商品",
  376. SortOrder: 2,
  377. },
  378. // 面料示例
  379. {
  380. ID: generateID("fabric", "COTTON"),
  381. Type: "fabric",
  382. Code: "COTTON",
  383. Name: "棉",
  384. Description: "棉质面料",
  385. SortOrder: 1,
  386. },
  387. {
  388. ID: generateID("fabric", "POLYESTER"),
  389. Type: "fabric",
  390. Code: "POLYESTER",
  391. Name: "涤纶",
  392. Description: "涤纶面料",
  393. SortOrder: 2,
  394. },
  395. {
  396. ID: generateID("fabric", "WOOL"),
  397. Type: "fabric",
  398. Code: "WOOL",
  399. Name: "羊毛",
  400. Description: "羊毛面料",
  401. SortOrder: 3,
  402. },
  403. // 颜色色系示例
  404. {
  405. ID: generateID("color_family", "RED"),
  406. Type: "color_family",
  407. Code: "RED",
  408. Name: "红色系",
  409. Description: "红色系列",
  410. SortOrder: 1,
  411. },
  412. {
  413. ID: generateID("color_family", "BLUE"),
  414. Type: "color_family",
  415. Code: "BLUE",
  416. Name: "蓝色系",
  417. Description: "蓝色系列",
  418. SortOrder: 2,
  419. },
  420. {
  421. ID: generateID("color_family", "BLACK"),
  422. Type: "color_family",
  423. Code: "BLACK",
  424. Name: "黑色系",
  425. Description: "黑色系列",
  426. SortOrder: 3,
  427. },
  428. // 尺码组示例
  429. {
  430. ID: generateID("size_group", "XS-S"),
  431. Type: "size_group",
  432. Code: "XS-S",
  433. Name: "超小-小号",
  434. Description: "超小号到小号",
  435. SortOrder: 1,
  436. },
  437. {
  438. ID: generateID("size_group", "M-L"),
  439. Type: "size_group",
  440. Code: "M-L",
  441. Name: "中号-大号",
  442. Description: "中号到大号",
  443. SortOrder: 2,
  444. },
  445. {
  446. ID: generateID("size_group", "XL-XXL"),
  447. Type: "size_group",
  448. Code: "XL-XXL",
  449. Name: "加大-特大号",
  450. Description: "加大号到特大号",
  451. SortOrder: 3,
  452. },
  453. }
  454. // 批量插入数据
  455. for _, dim := range dimensions {
  456. if err := insertOrUpdateProductDimension(dbFactory, dim); err != nil {
  457. logger.Warn("插入商品维度数据失败: type=%s, code=%s, error=%v", dim.Type, dim.Code, err)
  458. // 继续插入其他数据
  459. }
  460. }
  461. logger.Info("商品维度默认值注册完成,共 %d 条记录", len(dimensions))
  462. return nil
  463. }
  464. // 插入或更新店铺维度数据
  465. func insertOrUpdateStoreDimension(dbFactory *database.DBFactory, dim MasterStoreDimension) error {
  466. db := dbFactory.GetDB()
  467. if db == nil {
  468. return fmt.Errorf("数据库连接为空")
  469. }
  470. // 使用ON DUPLICATE KEY UPDATE逻辑
  471. // 注意:这里假设使用MySQL方言
  472. query := `INSERT INTO master_store_dimension (id, type, code, name, description, sort_order, extra_properties, created_at, updated_at)
  473. VALUES (?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
  474. ON DUPLICATE KEY UPDATE
  475. name = VALUES(name),
  476. description = VALUES(description),
  477. sort_order = VALUES(sort_order),
  478. extra_properties = VALUES(extra_properties),
  479. updated_at = NOW()`
  480. _, err := db.Exec(query, dim.ID, dim.Type, dim.Code, dim.Name, dim.Description, dim.SortOrder)
  481. return err
  482. }
  483. // 插入或更新商品维度数据
  484. func insertOrUpdateProductDimension(dbFactory *database.DBFactory, dim MasterProductDimension) error {
  485. db := dbFactory.GetDB()
  486. if db == nil {
  487. return fmt.Errorf("数据库连接为空")
  488. }
  489. query := `INSERT INTO master_product_dimension (id, type, code, name, description, sort_order, created_at, updated_at)
  490. VALUES (?, ?, ?, ?, ?, ?, NOW(), NOW())
  491. ON DUPLICATE KEY UPDATE
  492. name = VALUES(name),
  493. description = VALUES(description),
  494. sort_order = VALUES(sort_order),
  495. updated_at = NOW()`
  496. _, err := db.Exec(query, dim.ID, dim.Type, dim.Code, dim.Name, dim.Description, dim.SortOrder)
  497. return err
  498. }
  499. // 生成ID
  500. func generateID(dimType, code string) string {
  501. return fmt.Sprintf("%s_%s", dimType, code)
  502. }
  503. // 转换为JSON字符串
  504. func toJSON(data map[string]interface{}) string {
  505. if data == nil {
  506. return "{}"
  507. }
  508. jsonBytes, err := json.Marshal(data)
  509. if err != nil {
  510. return "{}"
  511. }
  512. return string(jsonBytes)
  513. }
  514. // ============================
  515. // 默认值注册使用示例
  516. // ============================
  517. // 示例:为主数据表注册默认值(如果需要)
  518. // func registerProductDefaults(dbFactory *database.DBFactory) error {
  519. // // 示例:插入一些默认的商品分类数据
  520. // // 注意:实际应用中,主数据通常从ERP系统同步,不需要默认值
  521. // return nil
  522. // }
  523. //
  524. // 在包的init()函数中注册:
  525. // func init() {
  526. // RegisterDefaultValues(registerProductDefaults)
  527. // }
  528. // 注意:要为其他表添加默认值,请遵循以下步骤:
  529. // 1. 在任意表文件中定义一个函数:func myTableDefaults(dbFactory *database.DBFactory) error
  530. // 2. 在函数的init()中调用RegisterDefaultValues注册该函数
  531. // 3. 确保函数在包初始化时被注册(init()函数会自动执行)
  532. // 4. 在应用启动时调用tables.RegisterAllDefaults(dbFactory)执行所有注册
  533. // 注册公司维度默认值
  534. func registerCompanyDimensionDefaults(dbFactory *database.DBFactory) error {
  535. if dbFactory == nil {
  536. return fmt.Errorf("数据库工厂为空")
  537. }
  538. dimensions := []MasterCompanyDimension{
  539. // 公司类型维度
  540. {
  541. ID: generateID("company_type", "SUPPLIER"),
  542. Type: "company_type",
  543. Code: "SUPPLIER",
  544. Name: "供应商",
  545. Description: "商品供应商,提供采购商品",
  546. SortOrder: 1,
  547. },
  548. {
  549. ID: generateID("company_type", "SUBSIDIARY"),
  550. Type: "company_type",
  551. Code: "SUBSIDIARY",
  552. Name: "子公司",
  553. Description: "集团下属子公司",
  554. SortOrder: 2,
  555. },
  556. {
  557. ID: generateID("company_type", "AGENT"),
  558. Type: "company_type",
  559. Code: "AGENT",
  560. Name: "代理商",
  561. Description: "品牌代理商,负责区域销售",
  562. SortOrder: 3,
  563. },
  564. {
  565. ID: generateID("company_type", "WHOLESALER"),
  566. Type: "company_type",
  567. Code: "WHOLESALER",
  568. Name: "批发商",
  569. Description: "批发销售商,批量采购销售",
  570. SortOrder: 4,
  571. },
  572. {
  573. ID: generateID("company_type", "GROUP"),
  574. Type: "company_type",
  575. Code: "GROUP",
  576. Name: "集团",
  577. Description: "集团公司总部",
  578. SortOrder: 5,
  579. },
  580. {
  581. ID: generateID("company_type", "FRANCHISEE"),
  582. Type: "company_type",
  583. Code: "FRANCHISEE",
  584. Name: "加盟商",
  585. Description: "品牌加盟商",
  586. SortOrder: 6,
  587. },
  588. {
  589. ID: generateID("company_type", "CUSTOMER"),
  590. Type: "company_type",
  591. Code: "CUSTOMER",
  592. Name: "客户",
  593. Description: "终端客户",
  594. SortOrder: 7,
  595. },
  596. {
  597. ID: generateID("company_type", "LOGISTICS"),
  598. Type: "company_type",
  599. Code: "LOGISTICS",
  600. Name: "物流商",
  601. Description: "物流运输服务商",
  602. SortOrder: 8,
  603. },
  604. }
  605. for _, dimension := range dimensions {
  606. query := `INSERT INTO master_company_dimension (id, type, code, name, description, sort_order, extra_properties, created_at, updated_at)
  607. VALUES (?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
  608. ON DUPLICATE KEY UPDATE name = VALUES(name), description = VALUES(description), sort_order = VALUES(sort_order), extra_properties = VALUES(extra_properties), updated_at = NOW()`
  609. if _, err := dbFactory.GetDB().Exec(query,
  610. dimension.ID,
  611. dimension.Type,
  612. dimension.Code,
  613. dimension.Name,
  614. dimension.Description,
  615. dimension.SortOrder,
  616. ); err != nil {
  617. return fmt.Errorf("插入公司维度数据失败: %v", err)
  618. }
  619. }
  620. logger.Info("公司维度默认值注册完成")
  621. return nil
  622. }