company_type.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. package main
  2. import (
  3. "fmt"
  4. "github.com/xuri/excelize/v2"
  5. util "jygit.jydev.jianyu360.cn/data_processing/common_utils"
  6. "log"
  7. "regexp"
  8. "strings"
  9. )
  10. // matchCompanyCode 根据企业库有的类型,匹配对应标准法人库类型
  11. func matchCompanyCode() {
  12. filePath := "company_types_finish.xlsx"
  13. // 1. 读取 Excel(获取 A 列数据)
  14. f, err := excelize.OpenFile(filePath)
  15. if err != nil {
  16. log.Fatal("❌ 无法打开 Excel 文件:", err)
  17. }
  18. defer f.Close()
  19. //读取央企
  20. rows, err := f.GetRows("企业库所有类型")
  21. if err != nil {
  22. log.Fatal("❌ 无法读取 企业所有类型:", err)
  23. }
  24. // 🔍 正则,用于提取4位数字
  25. re4 := regexp.MustCompile(`\d{4}`)
  26. for i := 1; i < len(rows); i++ {
  27. name := rows[i][0]
  28. log.Println("name", name)
  29. // 去除引号
  30. cleanText := strings.ReplaceAll(name, `"`, "")
  31. cleanText = strings.TrimSpace(cleanText)
  32. // 替换中文括号为英文括号
  33. cleanText = strings.ReplaceAll(cleanText, "(", "(")
  34. cleanText = strings.ReplaceAll(cleanText, ")", ")")
  35. var code string
  36. // 优先提取4位数字
  37. if m := re4.FindString(cleanText); m != "" {
  38. code = m
  39. } else {
  40. // 去除引号后完全匹配
  41. if c, ok := codeMap[cleanText]; ok {
  42. code = c
  43. }
  44. }
  45. if code == "" {
  46. code = getCodeByCompanyType(cleanText, codeMap)
  47. }
  48. tt := nameMap[code]
  49. f.SetCellValue("企业库所有类型", fmt.Sprintf("D%v", i+1), code)
  50. f.SetCellValue("企业库所有类型", fmt.Sprintf("E%v", i+1), tt)
  51. }
  52. f.Save()
  53. }
  54. // getCodeType 根据企业名称,获取经营主体代码标签
  55. func getCodeType(name string) (tab1, tab2 string) {
  56. where := map[string]interface{}{
  57. "use_flag": 0,
  58. "company_status": map[string]interface{}{
  59. "$nin": []string{"注销", "吊销", "吊销,已注销"},
  60. },
  61. "company_name": name,
  62. }
  63. // 🔍 正则,用于提取4位数字
  64. re4 := regexp.MustCompile(`\d{4}`)
  65. top_bases, _ := Mgo181.FindOne("company_base", where)
  66. company_type := util.ObjToString((*top_bases)["company_type"])
  67. // 去除引号
  68. cleanText := strings.ReplaceAll(company_type, `"`, "")
  69. cleanText = strings.TrimSpace(cleanText)
  70. // 替换中文括号为英文括号
  71. cleanText = strings.ReplaceAll(cleanText, "(", "(")
  72. cleanText = strings.ReplaceAll(cleanText, ")", ")")
  73. cleanText = strings.ReplaceAll(cleanText, "外资比例低于25%", "")
  74. // 判断是不是日期(如 2008/10/31)
  75. if matched, _ := regexp.MatchString(`^\d{4}/\d{1,2}/\d{1,2}$`, cleanText); matched {
  76. log.Printf("跳过日期行: %s", cleanText)
  77. return
  78. }
  79. // 如果包含“年”/“月”/“日”等,也跳过(不提取数字)
  80. if strings.Contains(cleanText, "年") || strings.Contains(cleanText, "月") || strings.Contains(cleanText, "日") {
  81. log.Printf("跳过含日期描述的行: %s", cleanText)
  82. return
  83. }
  84. var code string
  85. // 优先提取4位数字
  86. if m := re4.FindString(cleanText); m != "" {
  87. code = m
  88. } else {
  89. // 去除引号后完全匹配
  90. if c, ok := codeMap[cleanText]; ok {
  91. code = c
  92. }
  93. }
  94. if code == "" {
  95. code = getCodeByCompanyType(cleanText, codeMap)
  96. if code != "" {
  97. tab1 = codeZhu[code]
  98. tab2 = codeZhu2[code]
  99. }
  100. } else {
  101. tab1 = codeZhu[code]
  102. tab2 = codeZhu2[code]
  103. }
  104. return
  105. }
  106. // getCompanyType 获取公司类型;央企、国企、央企下属、事业单位、民企
  107. func getCompanyType(name string) (company_type string) {
  108. if name == "" {
  109. return
  110. }
  111. if yangMap[name] {
  112. company_type = "央企"
  113. return
  114. }
  115. if yangChildMap[name] {
  116. company_type = "央企下属"
  117. return
  118. }
  119. where := map[string]interface{}{
  120. "company_name": name,
  121. }
  122. // special_enterprise 事业单位
  123. enterprise, _ := Mgo181.FindOne("special_enterprise", where)
  124. if enterprise != nil && (len(*enterprise)) > 0 {
  125. company_type = "事业单位"
  126. return
  127. }
  128. //special_gov_unit 机关单位
  129. gov, _ := Mgo181.FindOne("special_gov_unit", where)
  130. if gov != nil && (len(*gov)) > 0 {
  131. company_type = "党政机关"
  132. return
  133. }
  134. //special_social_organ 社会团体
  135. soc, _ := Mgo181.FindOne("special_social_organ", where)
  136. if soc != nil && (len(*soc)) > 0 {
  137. company_type = "社会团体"
  138. return
  139. }
  140. //铁塔智联技术有限公司重庆市分公司
  141. if strings.Contains(name, "铁塔") {
  142. if strings.Contains(name, "分公司") {
  143. company_type = "地方国企"
  144. return
  145. } else {
  146. company_type = "国企"
  147. return
  148. }
  149. }
  150. //company_base
  151. where["use_flag"] = 0
  152. bases, _ := Mgo181.Find("company_base", where, nil, nil, false, -1, -1)
  153. if bases != nil && (len(*bases)) > 0 {
  154. for _, v := range *bases {
  155. if strings.Contains(util.ObjToString(v["company_status"]), "吊销") || strings.Contains(util.ObjToString(v["company_status"]), "注销") || util.ObjToString((v)["company_type"]) == "" {
  156. continue
  157. } else {
  158. bty := util.ObjToString((v)["company_type"])
  159. if strings.Contains(bty, "国有独资") || strings.Contains(bty, "国有控股") ||
  160. bty == "全民所有制" || bty == "集体所有制" ||
  161. bty == "国有事业单位营业" || bty == "集体事业单位营业" ||
  162. bty == "国有社团法人营业" || bty == "国有经营单位(非法人)" || bty == "集体经营单位(非法人)" {
  163. company_type = "国企"
  164. return
  165. }
  166. // 地方国企
  167. //par_name := getTop(name, false)
  168. par_names := getTopNames(name)
  169. if len(par_names) > 0 {
  170. for _, par_name := range par_names {
  171. topwhere := map[string]interface{}{
  172. "use_flag": 0,
  173. "company_status": map[string]interface{}{
  174. "$nin": []string{"注销", "吊销", "吊销,已注销"},
  175. },
  176. "company_name": par_name,
  177. }
  178. top_bases, _ := Mgo181.FindOne("company_base", topwhere)
  179. if top_bases == nil && len(*top_bases) == 0 {
  180. if strings.Contains(par_name, "(") && strings.Contains(par_name, ")") {
  181. par_name = strings.ReplaceAll(par_name, ")", ")")
  182. par_name = strings.ReplaceAll(par_name, "(", "(")
  183. }
  184. }
  185. if top_bases != nil && len(*top_bases) > 0 {
  186. top_company_type := util.ObjToString((*top_bases)["company_type"])
  187. if strings.Contains(top_company_type, "国有独资") || strings.Contains(top_company_type, "国有控股") ||
  188. top_company_type == "全民所有制" || top_company_type == "集体所有制" ||
  189. top_company_type == "国有事业单位营业" || top_company_type == "集体事业单位营业" ||
  190. top_company_type == "国有社团法人营业" || top_company_type == "国有经营单位(非法人)" || top_company_type == "集体经营单位(非法人)" || top_company_type == "事业单位" {
  191. company_type = "地方国企"
  192. return
  193. }
  194. } else {
  195. // 去政府机关和事业单位查询
  196. where2 := map[string]interface{}{
  197. "company_name": par_name,
  198. }
  199. // special_enterprise 事业单位
  200. enterprise, _ := Mgo181.FindOne("special_enterprise", where2)
  201. if enterprise != nil && (len(*enterprise)) > 0 {
  202. company_type = "地方国企"
  203. return
  204. }
  205. //special_gov_unit 机关单位
  206. gov, _ := Mgo181.FindOne("special_gov_unit", where2)
  207. if gov != nil && (len(*gov)) > 0 {
  208. company_type = "地方国企"
  209. return
  210. }
  211. }
  212. }
  213. }
  214. }
  215. }
  216. }
  217. //company_type = "民企"
  218. return
  219. }
  220. // getMarketType 获取上市公司类型;A股、新三板、非上市
  221. func getMarketType(name string) (stype string) {
  222. stype = "非上市"
  223. where := map[string]interface{}{
  224. "company_name": name,
  225. "use_flag": 0,
  226. }
  227. bases, _ := Mgo181.Find("company_base", where, nil, nil, false, -1, -1)
  228. if bases != nil && (len(*bases)) > 0 {
  229. for _, v := range *bases {
  230. if strings.Contains(util.ObjToString(v["company_status"]), "吊销") || strings.Contains(util.ObjToString(v["company_status"]), "注销") {
  231. continue
  232. } else {
  233. list_code := util.ObjToString((v)["list_code"])
  234. if list_code == "" {
  235. continue
  236. }
  237. //新三板股票代码 开头
  238. if strings.HasPrefix(list_code, "43") || strings.HasPrefix(list_code, "83") || strings.HasPrefix(list_code, "87") || strings.HasPrefix(list_code, "88") {
  239. stype = "新三板"
  240. return
  241. } else {
  242. stype = "A股"
  243. return
  244. }
  245. }
  246. }
  247. }
  248. return
  249. }
  250. // getTop 获取最上级公司
  251. func getTop(name string) (top string) {
  252. if name == "" {
  253. return
  254. }
  255. currName := name
  256. firstSearch := true
  257. visited := make(map[string]bool)
  258. visited[currName] = true
  259. for {
  260. topTmp := getParentsByPartner1(currName)
  261. topName := util.ObjToString(topTmp["stock_name"])
  262. // 第一次查找就失败,直接返回空
  263. if firstSearch && topName == "" {
  264. return
  265. }
  266. firstSearch = false
  267. // 非第一次查找,上级为空,返回当前获取到的上级
  268. if topName == "" {
  269. return currName
  270. }
  271. // 避免循环:如果 topName 与 currName 相同,或 topName 已访问过,说明进入环路
  272. if topName == currName || visited[topName] {
  273. return currName
  274. }
  275. // 如果 topName 不符合要求,比如不含“公司”,也返回当前
  276. if !strings.Contains(topName, "公司") && !strings.Contains(topName, "集团") {
  277. return currName
  278. }
  279. // 更新当前公司名,继续向上找
  280. currName = topName
  281. visited[currName] = true
  282. }
  283. }
  284. // getParentsByPartner1 返回投资比例50%以上的上级企业
  285. func getParentsByPartner1(companyName string) (res map[string]interface{}) {
  286. q := map[string]interface{}{"company_name": companyName, "use_flag": 0, "is_history": 0, "is_personal": 0}
  287. info, _ := Mgo181.Find("company_partner", q, nil, nil, false, -1, -1)
  288. if info == nil || len(*info) == 0 {
  289. return
  290. }
  291. for _, v := range *info {
  292. // 不是法人企业,直接跳过
  293. if !strings.Contains(util.ObjToString(v["stock_type"]), "法人") {
  294. continue
  295. }
  296. // 投资比例 必须 0.5以上
  297. stock_proportion := util.Float64All(v["stock_proportion"])
  298. if stock_proportion >= 0.5 {
  299. return v
  300. }
  301. }
  302. return
  303. }
  304. // getParentsByPartner 获取母公司,返回投资比例最大的企业
  305. func getParentsByPartner(companyName string) (res map[string]interface{}) {
  306. q := map[string]interface{}{"company_name": companyName, "use_flag": 0, "is_history": 0, "is_personal": 0}
  307. info, _ := Mgo181.Find("company_partner", q, nil, nil, false, -1, -1)
  308. if info == nil || len(*info) == 0 {
  309. return
  310. }
  311. var maxProportion float64
  312. for _, v := range *info {
  313. // 不是法人企业,直接跳过
  314. if !strings.Contains(util.ObjToString(v["stock_type"]), "法人") {
  315. continue
  316. }
  317. // 获取比例
  318. stockProportion := util.Float64All(v["stock_proportion"])
  319. // 比较当前比例是否更大
  320. if stockProportion > maxProportion {
  321. maxProportion = stockProportion
  322. res = v
  323. }
  324. }
  325. return
  326. }
  327. // getTopCompanyType 寻找上级企业
  328. func getTopNames(name string) (res []string) {
  329. if name == "" {
  330. return
  331. }
  332. currName := name
  333. firstSearch := true
  334. visited := make(map[string]bool)
  335. visited[currName] = true
  336. for {
  337. topTmp := getParentsByPartner(currName)
  338. topName := util.ObjToString(topTmp["stock_name"])
  339. // 第一次查找就失败,直接返回空
  340. if firstSearch && topName == "" {
  341. return
  342. }
  343. firstSearch = false
  344. // 非第一次查找,上级为空,返回当前获取到的上级
  345. if topName == "" {
  346. return
  347. }
  348. // 避免循环:如果 topName 与 currName 相同,或 topName 已访问过,说明进入环路
  349. if topName == currName || visited[topName] {
  350. return
  351. }
  352. // 更新当前公司名,继续向上找
  353. currName = topName
  354. visited[currName] = true
  355. res = append(res, topName)
  356. }
  357. }