biddingtask.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. package main
  2. import (
  3. "mongodb"
  4. "qfw/util"
  5. "qfw/util/redis"
  6. "reflect"
  7. "regexp"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "unicode/utf8"
  12. u "util"
  13. )
  14. var date1 = regexp.MustCompile("20[0-2][0-9][年|\\-/.][0-9]{1,2}[月|\\-/.][0-9]{1,2}[日]?")
  15. // @Description 合并extract 字段到bidding表
  16. // @Author J 2022/6/7 2:25 PM
  17. func MergeExtract(tmp, compare, update map[string]interface{}, extractMap map[string]map[string]interface{}, tasktype string) (map[string]interface{}, map[string]interface{}) {
  18. tid := mongodb.BsonIdToSId(tmp["_id"])
  19. if extractMap[tid] != nil {
  20. compare = extractMap[tid]
  21. if tasktype == "bidding" {
  22. // 增量id段 正常数据
  23. if num := util.IntAll(compare["dataging"]); num == 1 { //extract中dataging=1跳过
  24. tmp = make(map[string]interface{})
  25. compare = nil
  26. return compare, update
  27. }
  28. delete(extractMap, tid)
  29. }
  30. if tasktype == "bidding_history" {
  31. //增量id段 历史数据
  32. if compare["history_updatetime"] == nil { //extract中history_updatetime不存在跳过
  33. tmp = make(map[string]interface{})
  34. compare = nil
  35. return compare, update
  36. }
  37. delete(extractMap, tid)
  38. }
  39. //更新bidding表,生成索引;bidding表modifyinfo中的字段不更新
  40. modifyinfo := make(map[string]bool)
  41. if tmpmodifyinfo, ok := tmp["modifyinfo"].(map[string]interface{}); ok && tmpmodifyinfo != nil {
  42. for k, _ := range tmpmodifyinfo {
  43. modifyinfo[k] = true
  44. }
  45. }
  46. //更新bidding表,生成索引
  47. for _, k := range biddingMgoFields {
  48. v1 := compare[k] //extract
  49. v2 := tmp[k] //bidding
  50. if v2 == nil && v1 != nil && !modifyinfo[k] {
  51. update[k] = v1
  52. } else if v2 != nil && v1 != nil && !modifyinfo[k] {
  53. //update[k+"_b"] = v2
  54. update[k] = v1
  55. } else if v2 != nil && v1 == nil {
  56. //update[k+"_b"] = v2
  57. if k == "area" || k == "city" || k == "district" {
  58. update[k] = ""
  59. }
  60. }
  61. }
  62. if util.IntAll(compare["repeat"]) == 1 {
  63. update["extracttype"] = -1
  64. } else {
  65. update["extracttype"] = 1
  66. }
  67. } else {
  68. compare = nil
  69. if util.IntAll(tmp["dataging"]) == 1 { //修改未抽取的bidding数据的dataging
  70. update["dataging"] = 0
  71. }
  72. }
  73. return compare, update
  74. }
  75. // @Description subscopeclass、topscopeclass、package
  76. // @Author J 2022/6/7 5:54 PM
  77. func FieldMethod(compare, update map[string]interface{}) {
  78. subscopeclass, _ := compare["subscopeclass"].([]interface{}) //subscopeclass
  79. if subscopeclass != nil {
  80. m1 := map[string]bool{}
  81. newclass := []string{}
  82. for _, sc := range subscopeclass {
  83. sclass, _ := sc.(string)
  84. if !m1[sclass] {
  85. m1[sclass] = true
  86. newclass = append(newclass, sclass)
  87. }
  88. }
  89. update["s_subscopeclass"] = strings.Join(newclass, ",")
  90. update["subscopeclass"] = newclass
  91. }
  92. topscopeclass, _ := compare["topscopeclass"].([]interface{}) //topscopeclass
  93. if topscopeclass != nil {
  94. m2 := map[string]bool{}
  95. newclass := []string{}
  96. for _, tc := range topscopeclass {
  97. tclass, _ := tc.(string)
  98. tclass = reg_letter.ReplaceAllString(tclass, "") // 去除字母
  99. if !m2[tclass] {
  100. m2[tclass] = true
  101. newclass = append(newclass, tclass)
  102. }
  103. }
  104. update["s_topscopeclass"] = strings.Join(newclass, ",")
  105. }
  106. if package1 := compare["package"]; package1 != nil {
  107. packageM, _ := package1.(map[string]interface{})
  108. for _, p := range packageM {
  109. pm, _ := p.(map[string]interface{})
  110. if util.ObjToString(pm["winner"]) != "" || util.Float64All(pm["budget"]) > 0 ||
  111. util.Float64All(pm["bidamount"]) > 0 {
  112. update["multipackage"] = 1
  113. break
  114. }
  115. }
  116. } else {
  117. update["multipackage"] = 0
  118. }
  119. }
  120. // @Description ES保存字段
  121. // @Author J 2022/6/7 11:34 AM
  122. func (t *TaskInfo) GetEsField(tmp, update map[string]interface{}) map[string]interface{} {
  123. newTmp := make(map[string]interface{})
  124. for field, ftype := range biddingEsFields {
  125. if tmp[field] != nil { //
  126. if field == "projectinfo" {
  127. mp, _ := tmp[field].(map[string]interface{})
  128. if mp != nil {
  129. newmap := map[string]interface{}{}
  130. for k, ktype := range projectinfoFields {
  131. mpv := mp[k]
  132. if mpv != nil && reflect.TypeOf(mpv).String() == ktype {
  133. newmap[k] = mp[k]
  134. }
  135. }
  136. if len(newmap) > 0 {
  137. newTmp[field] = newmap
  138. }
  139. }
  140. } else if field == "purchasinglist" { //标的物处理
  141. purchasinglist_new := []map[string]interface{}{}
  142. if pcl, _ := tmp[field].([]interface{}); len(pcl) > 0 {
  143. for _, ls := range pcl {
  144. lsm_new := make(map[string]interface{})
  145. lsm := ls.(map[string]interface{})
  146. for pf, pftype := range purchasinglistFields {
  147. lsmv := lsm[pf]
  148. if lsmv != nil && reflect.TypeOf(lsmv).String() == pftype {
  149. lsm_new[pf] = lsm[pf]
  150. }
  151. }
  152. if lsm_new != nil && len(lsm_new) > 0 {
  153. purchasinglist_new = append(purchasinglist_new, lsm_new)
  154. }
  155. }
  156. }
  157. if len(purchasinglist_new) > 0 {
  158. newTmp[field] = purchasinglist_new
  159. }
  160. } else if field == "procurementlist" {
  161. if tmp["procurementlist"] != nil {
  162. var arr []interface{}
  163. plist := tmp["procurementlist"].([]interface{})
  164. for _, p := range plist {
  165. p1 := p.(map[string]interface{})
  166. p2 := make(map[string]interface{})
  167. for k, v := range procurementlisFields {
  168. if k == "projectname" && util.ObjToString(p1[k]) == "" {
  169. p2[k] = util.ObjToString(tmp["projectname"])
  170. } else if k == "buyer" && util.ObjToString(p1[k]) == "" && util.ObjToString(tmp["buyer"]) != "" {
  171. p2[k] = util.ObjToString(tmp["buyer"])
  172. } else if k == "expurasingtime" && util.ObjToString(p1[k]) != "" {
  173. res := getMethod(util.ObjToString(p1[k]))
  174. if res != 0 {
  175. p2[k] = res
  176. }
  177. } else if p1[k] != nil && reflect.TypeOf(p1[k]).String() == v {
  178. p2[k] = p1[k]
  179. }
  180. }
  181. arr = append(arr, p2)
  182. }
  183. if len(arr) > 0 {
  184. newTmp[field] = arr
  185. }
  186. }
  187. } else if field == "projectscope" {
  188. ps, _ := tmp["projectscope"].(string)
  189. if len(ps) > pscopeLength {
  190. tmp["projectscope"] = string(([]rune(ps))[:pscopeLength])
  191. }
  192. } else if field == "winnerorder" { //中标候选
  193. winnerorder_new := []map[string]interface{}{}
  194. if winnerorder, _ := tmp[field].([]interface{}); len(winnerorder) > 0 {
  195. for _, win := range winnerorder {
  196. winMap_new := make(map[string]interface{})
  197. winMap := win.(map[string]interface{})
  198. for wf, wftype := range winnerorderlistFields {
  199. wfv := winMap[wf]
  200. if wfv != nil && reflect.TypeOf(wfv).String() == wftype {
  201. if wf == "sort" && util.Int64All(wfv) > 100 {
  202. continue
  203. }
  204. winMap_new[wf] = winMap[wf]
  205. }
  206. }
  207. if winMap_new != nil && len(winMap_new) > 0 {
  208. winnerorder_new = append(winnerorder_new, winMap_new)
  209. }
  210. }
  211. }
  212. if len(winnerorder_new) > 0 {
  213. newTmp[field] = winnerorder_new
  214. }
  215. } else if field == "qualifies" {
  216. //项目资质
  217. qs := []string{}
  218. if q, _ := tmp[field].([]interface{}); len(q) > 0 {
  219. for _, v := range q {
  220. v1 := v.(map[string]interface{})
  221. qs = append(qs, util.ObjToString(v1["key"]))
  222. }
  223. }
  224. if len(qs) > 0 {
  225. newTmp[field] = strings.Join(qs, ",")
  226. }
  227. } else if field == "review_experts" {
  228. // 评审专家
  229. if arr, ok := tmp["review_experts"].([]interface{}); ok && len(arr) > 0 {
  230. arr1 := util.ObjArrToStringArr(arr)
  231. newTmp[field] = strings.Join(arr1, ",")
  232. }
  233. } else if field == "bidopentime" {
  234. if tmp[field] != nil && tmp["bidendtime"] == nil {
  235. newTmp["bidendtime"] = tmp[field]
  236. newTmp[field] = tmp[field]
  237. } else if tmp[field] == nil && tmp["bidendtime"] != nil {
  238. newTmp["bidendtime"] = tmp[field]
  239. newTmp[field] = tmp["bidendtime"]
  240. } else {
  241. if tmp["bidopentime"] != nil {
  242. newTmp[field] = tmp["bidopentime"]
  243. }
  244. }
  245. } else if field == "detail" { //过滤
  246. detail, _ := tmp[field].(string)
  247. if len([]rune(detail)) > detailLength {
  248. detail = detail[:detailLength]
  249. }
  250. detail = filterSpace.ReplaceAllString(detail, "")
  251. if t.stype == "bidding" || t.stype == "bidding_history" {
  252. text, b := FilterDetail(detail)
  253. newTmp[field] = util.ObjToString(tmp["title"]) + " " + text
  254. update["cleartag"] = b
  255. } else {
  256. if tmp["cleartag"] != nil && tmp["cleartag"].(bool) {
  257. text, _ := FilterDetail(detail)
  258. newTmp[field] = util.ObjToString(tmp["title"]) + " " + text
  259. } else {
  260. newTmp[field] = util.ObjToString(tmp["title"]) + " " + detail
  261. }
  262. }
  263. } else if field == "_id" || field == "topscopeclass" || field == "entidlist" { //不做处理
  264. newTmp[field] = tmp[field]
  265. } else if field == "publishtime" || field == "comeintime" {
  266. //字段类型不正确,特别处理
  267. if tmp[field] != nil && util.Int64All(tmp[field]) > 0 {
  268. newTmp[field] = util.Int64All(tmp[field])
  269. }
  270. } else { //其它字段判断数据类型,不正确舍弃
  271. if fieldval := tmp[field]; reflect.TypeOf(fieldval).String() != ftype {
  272. continue
  273. } else {
  274. if fieldval != "" {
  275. newTmp[field] = fieldval
  276. }
  277. }
  278. }
  279. }
  280. }
  281. filetext := getFileText(tmp)
  282. if len([]rune(filetext)) > 10 {
  283. newTmp["filetext"] = filetext
  284. } else {
  285. // 附件未识别到内容,有附件且附件能够下载 filetext=""
  286. if pinfo, o1 := tmp["projectinfo"].(map[string]interface{}); o1 {
  287. if atts, o2 := pinfo["attachments"].(map[string]interface{}); o2 {
  288. tag := false
  289. for _, at := range atts {
  290. at1 := at.(map[string]interface{})
  291. if at1["fid"] != nil {
  292. tag = true
  293. break
  294. }
  295. }
  296. if tag {
  297. newTmp["filetext"] = ""
  298. }
  299. }
  300. }
  301. }
  302. YuceEndtime(newTmp) // 预测结果时间
  303. if t.stype == "bidding" {
  304. newTmp["createtime"] = time.Now().Unix() // es库数据创建时间,只有增量数据有
  305. }
  306. return newTmp
  307. }
  308. // @Description 附件内容
  309. // @Author J 2022/6/7 1:54 PM
  310. func getFileText(tmp map[string]interface{}) (filetext string) {
  311. if attchMap, ok := tmp["attach_text"].(map[string]interface{}); attchMap != nil && ok {
  312. for _, tmpData1 := range attchMap {
  313. if tmpData2, ok := tmpData1.(map[string]interface{}); tmpData2 != nil && ok {
  314. for _, result := range tmpData2 {
  315. if resultMap, ok := result.(map[string]interface{}); resultMap != nil && ok {
  316. if attach_url := util.ObjToString(resultMap["attach_url"]); attach_url != "" {
  317. bs := u.OssGetObject(attach_url) //oss读数据
  318. if utf8.RuneCountInString(filetext+bs) < fileLength {
  319. filetext += bs + "\n"
  320. } else {
  321. if utf8.RuneCountInString(bs) > fileLength {
  322. filetext = bs[0:fileLength]
  323. } else {
  324. filetext = bs
  325. }
  326. break
  327. }
  328. }
  329. }
  330. }
  331. }
  332. }
  333. }
  334. return
  335. }
  336. // 预测结果时间
  337. func YuceEndtime(tmp map[string]interface{}) {
  338. flag := true
  339. scope := []string{"服务采购_法律咨询", "服务采购_会计", "服务采购_物业", "服务采购_审计", "服务采购_安保", "服务采购_仓储物流",
  340. "服务采购_广告宣传印刷"}
  341. subscopeclass := util.ObjToString(tmp["s_subscopeclass"])
  342. for _, v := range scope {
  343. if strings.Contains(subscopeclass, v) {
  344. flag = false
  345. break
  346. }
  347. }
  348. if flag {
  349. return
  350. }
  351. subtype := util.ObjToString(tmp["subtype"])
  352. if subtype == "成交" || subtype == "合同" {
  353. // yucestarttime、yuceendtime
  354. yucestarttime, yuceendtime := int64(0), int64(0)
  355. // 项目周期中
  356. if util.ObjToString(tmp["projectperiod"]) != "" {
  357. dateStr := date1.FindStringSubmatch(util.ObjToString(tmp["projectperiod"]))
  358. if len(dateStr) == 2 {
  359. sdate := FormatDateStr(dateStr[0])
  360. edate := FormatDateStr(dateStr[1])
  361. if sdate < edate && sdate != 0 && edate != 0 {
  362. yucestarttime = sdate
  363. yuceendtime = edate
  364. }
  365. }
  366. }
  367. if yucestarttime > 0 && yuceendtime > yucestarttime {
  368. tmp["yuceendtime"] = yuceendtime
  369. return
  370. }
  371. // 预测开始时间 合同签订日期
  372. if yucestarttime == 0 {
  373. if util.IntAll(tmp["signaturedate"]) <= 0 {
  374. if util.IntAll(tmp["publishtime"]) <= 0 {
  375. return
  376. } else {
  377. yucestarttime = util.Int64All(tmp["publishtime"])
  378. }
  379. } else {
  380. yucestarttime = util.Int64All(tmp["signaturedate"])
  381. }
  382. }
  383. // 预测结束时间
  384. if yucestarttime > 0 && yuceendtime == 0 {
  385. if util.IntAll(tmp["project_duration"]) > 0 && util.ObjToString(tmp["project_timeunit"]) != "" {
  386. yuceendtime = YcEndTime(yucestarttime, util.IntAll(tmp["project_duration"]), util.ObjToString(tmp["project_timeunit"]))
  387. tmp["yuceendtime"] = yuceendtime
  388. }
  389. }
  390. }
  391. }
  392. func YcEndTime(starttime int64, num int, unit string) int64 {
  393. yuceendtime := int64(0)
  394. if unit == "日历天" || unit == "天" || unit == "日" {
  395. yuceendtime = starttime + int64(num*86400)
  396. } else if unit == "周" {
  397. yuceendtime = time.Unix(starttime, 0).AddDate(0, 0, num*7).Unix()
  398. } else if unit == "月" {
  399. yuceendtime = time.Unix(starttime, 0).AddDate(0, num, 0).Unix()
  400. } else if unit == "年" {
  401. yuceendtime = time.Unix(starttime, 0).AddDate(num, 0, 0).Unix()
  402. } else if unit == "工作日" {
  403. n := num / 7 * 2
  404. yuceendtime = time.Unix(starttime, 0).AddDate(0, 0, num+n).Unix()
  405. }
  406. return yuceendtime
  407. }
  408. func FormatDateStr(ds string) int64 {
  409. ds = strings.Replace(ds, "年", "-", -1)
  410. ds = strings.Replace(ds, "月", "-", -1)
  411. ds = strings.Replace(ds, "日", "", -1)
  412. ds = strings.Replace(ds, "/", "-", -1)
  413. ds = strings.Replace(ds, ".", "-", -1)
  414. location, err := time.ParseInLocation(util.Date_Short_Layout, ds, time.Local)
  415. if err != nil {
  416. util.Debug(err)
  417. return 0
  418. } else {
  419. return location.Unix()
  420. }
  421. }
  422. // @Description entidlist
  423. // @Author J 2022/6/7 2:36 PM
  424. func FieldFun(tmp map[string]interface{}) (cid []string) {
  425. sWinnerarr := strings.Split(util.ObjToString(tmp["s_winner"]), ",")
  426. for _, w := range sWinnerarr {
  427. if w != "" {
  428. id := redis.GetStr("qyxy_id", w)
  429. if id == "" {
  430. ents, _ := standardMgo.Find("qyxy_std", map[string]interface{}{"company_name": w}, map[string]interface{}{"updatetime": -1}, nil, false, -1, -1)
  431. if len(*ents) > 0 {
  432. id = util.ObjToString((*ents)[0]["_id"])
  433. redis.PutCKV("qyxy_id", w, id)
  434. } else {
  435. ent, _ := qyxyMgo.FindOne("company_history_name", map[string]interface{}{"history_name": w})
  436. if len(*ent) > 0 {
  437. id = util.ObjToString((*ent)["company_id"])
  438. redis.PutCKV("qyxy_id", w, id)
  439. }
  440. }
  441. }
  442. if id == "" {
  443. id = "-"
  444. }
  445. cid = append(cid, id)
  446. }
  447. }
  448. return cid
  449. }
  450. var filterSpace = regexp.MustCompile("<[^>]*?>|[\\s\u3000\u2003\u00a0]")
  451. func FilterDetail(text string) (string, bool) {
  452. b := false // 清理标记
  453. for _, s := range FilterKeyword {
  454. reg := regexp.MustCompile(s)
  455. if reg.MatchString(text) {
  456. text = reg.ReplaceAllString(text, "")
  457. if !b {
  458. b = true
  459. }
  460. }
  461. }
  462. return text, b
  463. }
  464. // 正则判断是否包含
  465. func checkContains(s, sub string) bool {
  466. reg := regexp.MustCompile(`(?i)(^|([\s\t\n]+))(` + sub + `)($|([\s\t\n]+))`)
  467. return reg.MatchString(s)
  468. }
  469. var TimeV1 = regexp.MustCompile("(\\d{4})[年.]?$")
  470. var TimeV2 = regexp.MustCompile("(\\d{4}[年.\\-/]?)(\\d{1,2}[月.\\-/]?$)")
  471. var TimeClear = regexp.MustCompile("[年|月|/|.|-]")
  472. // @Description 采购意向 预计采购时间处理
  473. // @Author J 2022/6/7 8:04 PM
  474. func getMethod(str string) int64 {
  475. if TimeV1.MatchString(str) {
  476. arr := TimeV1.FindStringSubmatch(str)
  477. st := arr[1] + "0000"
  478. parseInt, err := strconv.ParseInt(st, 10, 64)
  479. if err == nil {
  480. return parseInt
  481. }
  482. } else if TimeV2.MatchString(str) {
  483. arr := TimeV2.FindStringSubmatch(str)
  484. str1 := arr[2]
  485. if len(str1) == 1 {
  486. str1 = "0" + str1
  487. }
  488. str2 := TimeClear.ReplaceAllString(arr[1], "") + TimeClear.ReplaceAllString(str1, "") + "00"
  489. parseInt, err := strconv.ParseInt(str2, 10, 64)
  490. if err == nil {
  491. return parseInt
  492. }
  493. }
  494. return 0
  495. }
  496. // @Description 字段空值处理
  497. // @Author J 2022/6/7 8:04 PM
  498. func clearMap(tmp map[string]interface{}) {
  499. for k := range tmp {
  500. if purchasinglist, ok := tmp["purchasinglist"].([]interface{}); ok && len(purchasinglist) == 0 {
  501. delete(tmp, "purchasinglist")
  502. } else if reflect.TypeOf(tmp[k]).String() == "string" && util.ObjToString(tmp[k]) == "" {
  503. delete(tmp, k)
  504. }
  505. }
  506. }