company_type.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  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. top_company_type := util.ObjToString((*top_bases)["company_type"])
  181. if strings.Contains(top_company_type, "国有独资") || strings.Contains(top_company_type, "国有控股") ||
  182. top_company_type == "全民所有制" || top_company_type == "集体所有制" ||
  183. top_company_type == "国有事业单位营业" || top_company_type == "集体事业单位营业" ||
  184. top_company_type == "国有社团法人营业" || top_company_type == "国有经营单位(非法人)" || top_company_type == "集体经营单位(非法人)" || top_company_type == "事业单位" {
  185. company_type = "地方国企"
  186. return
  187. }
  188. } else {
  189. // 去政府机关和事业单位查询
  190. where2 := map[string]interface{}{
  191. "company_name": par_name,
  192. }
  193. // special_enterprise 事业单位
  194. enterprise, _ := Mgo181.FindOne("special_enterprise", where2)
  195. if enterprise != nil && (len(*enterprise)) > 0 {
  196. company_type = "地方国企"
  197. return
  198. }
  199. //special_gov_unit 机关单位
  200. gov, _ := Mgo181.FindOne("special_gov_unit", where2)
  201. if gov != nil && (len(*gov)) > 0 {
  202. company_type = "地方国企"
  203. return
  204. }
  205. }
  206. }
  207. }
  208. }
  209. }
  210. }
  211. //company_type = "民企"
  212. return
  213. }
  214. // getMarketType 获取上市公司类型;A股、新三板、非上市
  215. func getMarketType(name string) (stype string) {
  216. stype = "非上市"
  217. where := map[string]interface{}{
  218. "company_name": name,
  219. "use_flag": 0,
  220. }
  221. bases, _ := Mgo181.Find("company_base", where, nil, nil, false, -1, -1)
  222. if bases != nil && (len(*bases)) > 0 {
  223. for _, v := range *bases {
  224. if strings.Contains(util.ObjToString(v["company_status"]), "吊销") || strings.Contains(util.ObjToString(v["company_status"]), "注销") {
  225. continue
  226. } else {
  227. list_code := util.ObjToString((v)["list_code"])
  228. if list_code == "" {
  229. continue
  230. }
  231. //新三板股票代码 开头
  232. if strings.HasPrefix(list_code, "43") || strings.HasPrefix(list_code, "83") || strings.HasPrefix(list_code, "87") || strings.HasPrefix(list_code, "88") {
  233. stype = "新三板"
  234. return
  235. } else {
  236. stype = "A股"
  237. return
  238. }
  239. }
  240. }
  241. }
  242. return
  243. }
  244. // getTop 获取最上级公司
  245. // getTop 获取最上级公司;isCompany true 必须是企业类型,含有公司;
  246. func getTop(name string, isCompany bool) (top string) {
  247. if name == "" {
  248. return
  249. }
  250. currName := name
  251. firstSearch := true
  252. visited := make(map[string]bool)
  253. visited[currName] = true
  254. for {
  255. topTmp := getParentsByPartner(currName)
  256. topName := util.ObjToString(topTmp["stock_name"])
  257. // 第一次查找就失败,直接返回空
  258. if firstSearch && topName == "" {
  259. return
  260. }
  261. firstSearch = false
  262. // 非第一次查找,上级为空,返回当前获取到的上级
  263. if topName == "" {
  264. return currName
  265. }
  266. // 避免循环:如果 topName 与 currName 相同,或 topName 已访问过,说明进入环路
  267. if topName == currName || visited[topName] {
  268. return currName
  269. }
  270. if isCompany {
  271. // 如果 topName 不符合要求,比如不含“公司”,也返回当前
  272. if !strings.Contains(topName, "公司") {
  273. return currName
  274. }
  275. }
  276. // 更新当前公司名,继续向上找
  277. currName = topName
  278. visited[currName] = true
  279. }
  280. }
  281. // getParentsByPartner 获取母公司,返回投资比例最大的企业
  282. func getParentsByPartner(companyName string) (res map[string]interface{}) {
  283. q := map[string]interface{}{"company_name": companyName, "use_flag": 0, "is_history": 0, "is_personal": 0}
  284. info, _ := Mgo181.Find("company_partner", q, nil, nil, false, -1, -1)
  285. if info == nil || len(*info) == 0 {
  286. return
  287. }
  288. var maxProportion float64
  289. for _, v := range *info {
  290. // 不是法人企业,直接跳过
  291. if !strings.Contains(util.ObjToString(v["stock_type"]), "法人") {
  292. continue
  293. }
  294. // 获取比例
  295. stockProportion := util.Float64All(v["stock_proportion"])
  296. // 比较当前比例是否更大
  297. if stockProportion > maxProportion {
  298. maxProportion = stockProportion
  299. res = v
  300. }
  301. }
  302. return
  303. }
  304. // getTopCompanyType 寻找上级企业
  305. func getTopNames(name string) (res []string) {
  306. if name == "" {
  307. return
  308. }
  309. currName := name
  310. firstSearch := true
  311. visited := make(map[string]bool)
  312. visited[currName] = true
  313. for {
  314. topTmp := getParentsByPartner(currName)
  315. topName := util.ObjToString(topTmp["stock_name"])
  316. // 第一次查找就失败,直接返回空
  317. if firstSearch && topName == "" {
  318. return
  319. }
  320. firstSearch = false
  321. // 非第一次查找,上级为空,返回当前获取到的上级
  322. if topName == "" {
  323. return
  324. }
  325. // 避免循环:如果 topName 与 currName 相同,或 topName 已访问过,说明进入环路
  326. if topName == currName || visited[topName] {
  327. return
  328. }
  329. // 更新当前公司名,继续向上找
  330. currName = topName
  331. visited[currName] = true
  332. res = append(res, topName)
  333. }
  334. }