update.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. package main
  2. import (
  3. "github.com/go-xweb/log"
  4. "go.mongodb.org/mongo-driver/bson/primitive"
  5. "math"
  6. qu "qfw/util"
  7. "reflect"
  8. "sort"
  9. "strings"
  10. )
  11. func (p *ProjectTask) modifyUpdate(pInfoId string, index int, info *Info, tmp map[string]interface{}, tmpPro map[string]interface{}, modifyMap map[string]interface{}) {
  12. backupPro(tmpPro)
  13. infoList := []interface{}(tmpPro["list"].(primitive.A))
  14. infoMap := infoList[index].(map[string]interface{})
  15. infoList[index] = updateValue(infoMap, modifyMap)
  16. infofiled := InfoField{
  17. Budget: info.Budget,
  18. Bidamount: info.Bidamount,
  19. ContractCode: info.ContractCode,
  20. ProjectName: info.ProjectName,
  21. ProjectCode: info.ProjectCode,
  22. Bidstatus: info.SubType,
  23. }
  24. mapTmp, _ := tmpPro["infofiled"].(map[string]interface{})
  25. mapTmp[info.Id] = StructToMap(infofiled)
  26. set := map[string]interface{}{
  27. "$set": tmpPro,
  28. }
  29. _ = MongoTool.UpdateById(ProjectColl, pInfoId, set)
  30. }
  31. func (p *ProjectTask) mergeAndModify(pInfoId string, index int, info *Info, tmp map[string]interface{}, tmpPro map[string]interface{}, modifyMap map[string]interface{}) {
  32. p.AllIdsMapLock.Lock()
  33. currentPro := p.AllIdsMap[pInfoId]
  34. p.AllIdsMapLock.Unlock()
  35. merge, pId, i, comStr, mergePro := p.updateMerge(index, info, pInfoId, tmp, tmpPro)
  36. //招标信息在list中第1个
  37. if index == 0 {
  38. log.Println("第1条合并", "------1------")
  39. //快照
  40. backupPro(tmpPro)
  41. p.AllIdsMapLock.Lock()
  42. delete(p.AllIdsMap, pInfoId)
  43. p.AllIdsMapLock.Unlock()
  44. count := MongoTool.Delete(ProjectColl, pInfoId)
  45. log.Println(count)
  46. for _, infoId := range currentPro.P.Ids{
  47. if infoId == info.Id {
  48. continue
  49. }
  50. tmp1 := MongoTool.FindById(ExtractColl, infoId)
  51. p.fillInPlace(tmp)
  52. info1 := ParseInfo(tmp1)
  53. p.CommonMerge(tmp1, info1)
  54. }
  55. }else {
  56. log.Println("第n条合并", "------n------")
  57. //快照 招标信息所在的项目
  58. backupPro(tmpPro)
  59. if merge {
  60. //跟原项目list第0条信息作对比,可以合并
  61. if pId == pInfoId {
  62. //合并到当前项目
  63. mergeProject(p, currentPro.P, info, tmpPro, index)
  64. p.AllIdsMapLock.Lock()
  65. p.AllIdsMap[currentPro.P.Id.Hex()].P = currentPro.P
  66. p.AllIdsMapLock.Unlock()
  67. infoList := []interface{}(tmpPro["list"].(primitive.A))
  68. infoMap := infoList[index].(map[string]interface{})
  69. infoList[index] = updateValue(infoMap, modifyMap)
  70. infofiled := InfoField{
  71. Budget: info.Budget,
  72. Bidamount: info.Bidamount,
  73. ContractCode: info.ContractCode,
  74. ProjectName: info.ProjectName,
  75. ProjectCode: info.ProjectCode,
  76. Bidstatus: info.SubType,
  77. }
  78. mapTmp, _ := tmpPro["infofiled"].(map[string]interface{})
  79. mapTmp[info.Id] = StructToMap(infofiled)
  80. set := map[string]interface{}{
  81. "$set": tmpPro,
  82. }
  83. MongoTool.UpdateById(ProjectColl, pInfoId, set)
  84. }else {
  85. //合并到的其它项目里边
  86. //更新其它的项目
  87. pro := MongoTool.FindById(ProjectColl, mergePro.Id.Hex())
  88. backupPro(pro)
  89. choose, ex := p.CompareStatus(mergePro, info)
  90. if !choose {
  91. p.UpdateProject(tmp, info, mergePro, i, comStr, ex)
  92. }else {
  93. id, p1 := p.NewProject(tmp, info)
  94. p.AllIdsMapLock.Lock()
  95. p.AllIdsMap[id] = &ID{Id: id, P: p1}
  96. p.AllIdsMapLock.Unlock()
  97. }
  98. //内部合并
  99. p.innerMerge(currentPro.P, info, tmp, tmpPro)
  100. }
  101. }else {
  102. //合并到新建的项目里边,原有项目内部合并
  103. p.innerMerge(currentPro.P, info, tmp, tmpPro)
  104. }
  105. }
  106. }
  107. func (p *ProjectTask) updateMerge(index int, info *Info, pInfoId string, tmp map[string]interface{}, tmpPro map[string]interface{}) (bool, string, int, string, *ProjectInfo) {
  108. bpn, bpc, bptc, bpb, pids, _, IDArr := p.getCompareIds(info.ProjectName, info.ProjectCode, info.PTC, info.Buyer)
  109. defer p.wg.Done()
  110. for _, m := range pids {
  111. defer m.Lock.Unlock()
  112. }
  113. for _, id := range IDArr {
  114. defer id.Lock.Unlock()
  115. }
  116. bFindProject := false
  117. findPid := ""
  118. //获取完id,进行计算
  119. //定义两组
  120. comRes1 := []*ProjectInfo{} //优先级最高的对比结果数组
  121. comRes2 := []*ProjectInfo{} //优化级其次
  122. comRes3 := []*ProjectInfo{}
  123. for _, v := range IDArr {
  124. if index == 0 && pInfoId == v.P.Id.Hex() {
  125. //招标条目信息在原项目中是第0条时,忽略
  126. continue
  127. }
  128. comStr := ""
  129. compareProject := v.P
  130. compareProject.score = 0
  131. diffTime := int64(math.Abs(float64(info.Publishtime - compareProject.LastTime)))
  132. if diffTime <= p.validTime {
  133. //代理机构完全不相同,直接新建项目
  134. if CheckContain(compareProject.Agency, info.Agency) == 3 {
  135. continue
  136. }
  137. //地区(省、市、区)不同,直接新建项目
  138. if ComparePlace(compareProject, info) {
  139. continue
  140. }
  141. info.PNBH = 0
  142. info.PCBH = 0
  143. info.PTCBH = 0
  144. compareStr, score := comparePNC(info, compareProject)
  145. resVal, pjVal := Select(compareStr, info, compareProject)
  146. if resVal > 0 {
  147. compareBuyer, compareCity, compareTime, compareAgency, compareBudget, compareBidmount, score2 := p.compareBCTABB(info, compareProject, diffTime, score)
  148. //项目名称、项目编号、标题项目编号、采购单位、省、市、发布时间、代理机构
  149. comStr = compareStr + compareBuyer + compareCity + compareTime + compareAgency + compareBudget + compareBidmount
  150. compareProject.comStr = comStr
  151. compareProject.pjVal = pjVal
  152. compareProject.resVal = resVal
  153. eqV := compareResult(resVal, pjVal, score2, comStr, compareBuyer, compareCity, compareTime, compareAgency, compareBudget, compareBidmount)
  154. if eqV == 1 {
  155. comRes1 = append(comRes1, compareProject)
  156. } else if eqV == 2 {
  157. comRes2 = append(comRes2, compareProject)
  158. } else if eqV == 3 {
  159. comRes3 = append(comRes3, compareProject)
  160. }
  161. }
  162. }
  163. }
  164. //--------------------------------对比完成-----------------------
  165. k := -1
  166. comStr := ""
  167. mergePro := &ProjectInfo{}
  168. for kv, resN := range [][]*ProjectInfo{comRes1, comRes2, comRes3} {
  169. if len(resN) > 0 {
  170. if len(resN) > 1 {
  171. sort.Slice(resN, func(i, j int) bool {
  172. return resN[i].score > resN[j].score
  173. })
  174. }
  175. ex := 0
  176. resArr := []*ProjectInfo{}
  177. for _, res := range resN{
  178. choose, e := p.CompareStatus(resN[0], info)
  179. if !choose {
  180. ex = e
  181. resArr = append(resArr, res)
  182. }
  183. }
  184. if len(resArr) > 0 {
  185. bFindProject = true
  186. findPid = resArr[0].Id.Hex()
  187. for k2, bv := range []int{bpn, bpc, bptc, bpb} {
  188. if bv > -1 {
  189. pids[bv].Arr = append(pids[bv].Arr, findPid)
  190. if k2 == 0 {
  191. if resArr[0].ProjectName == "" {
  192. resArr[0].ProjectName = info.ProjectName
  193. } else {
  194. if resArr[0].MPN == nil {
  195. resArr[0].MPN = []string{info.ProjectName}
  196. } else {
  197. resArr[0].MPN = append(resArr[0].MPN, info.ProjectName)
  198. }
  199. }
  200. } else if k2 < 3 {
  201. if resArr[0].ProjectCode == "" {
  202. resArr[0].ProjectCode = qu.If(k2 == 1, info.ProjectCode, info.PTC).(string)
  203. } else {
  204. if resArr[0].MPC == nil {
  205. resArr[0].MPC = []string{qu.If(k2 == 1, info.ProjectCode, info.PTC).(string)}
  206. } else {
  207. resArr[0].MPC = append(resArr[0].MPC, qu.If(k2 == 1, info.ProjectCode, info.PTC).(string))
  208. }
  209. }
  210. } else {
  211. if resArr[0].Buyer == "" {
  212. resArr[0].Buyer = info.Buyer
  213. }
  214. }
  215. }
  216. }
  217. if index != 0 {
  218. //招标条目信息在原项目中是第非0条时,返回对比结果
  219. k = kv+1
  220. comStr = resArr[0].comStr
  221. mergePro = resArr[0]
  222. bFindProject = false
  223. findPid = ""
  224. }else {
  225. mergePro = resArr[0]
  226. //如果有合并,合并之前备份(快照)
  227. backupPro(tmpPro)
  228. p.UpdateProject(tmp, info, resArr[0], kv+1, resArr[0].comStr, ex)
  229. }
  230. }else {
  231. bFindProject = false
  232. findPid = ""
  233. }
  234. break
  235. }
  236. }
  237. if !bFindProject {
  238. id, p1 := p.NewProject(tmp, info)
  239. p.AllIdsMapLock.Lock()
  240. p.AllIdsMap[id] = &ID{Id: id, P: p1}
  241. p.AllIdsMapLock.Unlock()
  242. for _, m := range pids {
  243. m.Arr = append(m.Arr, id)
  244. }
  245. }
  246. return bFindProject, findPid, k, comStr, mergePro
  247. }
  248. //内部合并
  249. func (p *ProjectTask) innerMerge(pInfo *ProjectInfo, info *Info, tmp map[string]interface{}, tmpPro map[string]interface{}) {
  250. infoList := []interface{}(tmpPro["list"].(primitive.A))
  251. for index, info1 := range infoList{
  252. info2 := info1.(map[string]interface{})
  253. if info2["infoid"] == info.Id {
  254. deleteSlice1(infoList, info1)
  255. continue
  256. }
  257. mergeProject(p, pInfo, info, tmpPro, index)
  258. }
  259. mapTmp, _ := tmpPro["infofiled"].(map[string]interface{})
  260. delete(mapTmp, info.Id)
  261. set := map[string]interface{}{
  262. "$set": tmpPro,
  263. }
  264. MongoTool.UpdateById(ProjectColl, pInfo.Id.Hex(), set)
  265. }
  266. //合并字段到project
  267. func mergeProject(p *ProjectTask, pInfo *ProjectInfo, thisinfo *Info, set map[string]interface{}, index int) map[string]interface{} {
  268. //1--firsttime
  269. if thisinfo.Publishtime < pInfo.FirstTime && thisinfo.Publishtime > 0 {
  270. pInfo.FirstTime = thisinfo.Publishtime
  271. set["firsttime"] = thisinfo.Publishtime
  272. if thisinfo.TopType == "招标" {
  273. set["zbtime"] = thisinfo.Publishtime
  274. }
  275. }
  276. //2--lasttime
  277. pInfo.LastTime = thisinfo.Publishtime
  278. set["lasttime"] = thisinfo.Publishtime
  279. if thisinfo.TopType == "招标" {
  280. set["zbtime"] = thisinfo.Publishtime
  281. } else if thisinfo.TopType == "结果" || thisinfo.SubType == "合同" {
  282. set["jgtime"] = thisinfo.Publishtime
  283. }
  284. //废标、流标 处理时间
  285. if thisinfo.SubType == "流标" || thisinfo.SubType == "废标" {
  286. pInfo.FirstTime = thisinfo.Publishtime
  287. pInfo.Bidopentime = int64(0)
  288. pInfo.LastTime = thisinfo.Publishtime
  289. set["firsttime"] = thisinfo.Publishtime
  290. set["zbtime"] = int64(0)
  291. set["publishtime"] = thisinfo.Publishtime
  292. set["bidopentime"] = int64(0)
  293. }
  294. bt := thisinfo.TopType
  295. bs := thisinfo.SubType
  296. p.mapBidLock.Lock()
  297. if bt == "招标" {
  298. //招标状态,更新projectscope
  299. if thisinfo.ProjectScope != "" {
  300. set["projectscope"] = thisinfo.ProjectScope
  301. }
  302. set["bidtype"] = bidtype[bs]
  303. }else {
  304. set["bidtype"] = bt
  305. if bidstatus[bs] != "" {
  306. set["bidstatus"] = thisinfo.SubType
  307. } else if thisinfo.Infoformat == 2 {
  308. set["bidstatus"] = "拟建"
  309. } else {
  310. set["bidstatus"] = "其它"
  311. }
  312. }
  313. p.mapBidLock.Unlock()
  314. //3\4\5--省、市、县
  315. if thisinfo.Area != "全国" {
  316. //xt := true
  317. if pInfo.Area == "全国" {
  318. pInfo.Area = thisinfo.Area
  319. set["area"] = thisinfo.Area
  320. } else if pInfo.Area != thisinfo.Area {
  321. //xt = false
  322. }
  323. if pInfo.City == "" && thisinfo.City != "" {
  324. pInfo.City = thisinfo.City
  325. set["city"] = thisinfo.City
  326. } else if pInfo.City != thisinfo.City {
  327. //xt = false
  328. }
  329. if thisinfo.District != "" && pInfo.District == "" {
  330. pInfo.District = thisinfo.District
  331. set["district"] = thisinfo.District
  332. }
  333. }
  334. //6--项目名称
  335. if (thisinfo.ProjectName != "" && pInfo.ProjectName == "") || (len([]rune(pInfo.ProjectName)) < 6 && thisinfo.LenPN > 6) {
  336. pInfo.ProjectName = thisinfo.ProjectName
  337. set["projectname"] = thisinfo.ProjectName
  338. }
  339. //7--项目编号
  340. if (pInfo.ProjectCode == "" && thisinfo.ProjectCode != "") || (len([]rune(pInfo.ProjectCode)) < 6 && len([]rune(thisinfo.ProjectCode)) > 6) {
  341. pInfo.ProjectCode = thisinfo.ProjectCode
  342. set["projectcode"] = thisinfo.ProjectCode
  343. }
  344. //7--采购单位
  345. if (pInfo.Buyer == "" && thisinfo.Buyer != "") || (len([]rune(pInfo.Buyer)) < 5 && len([]rune(thisinfo.Buyer)) > 5) {
  346. pInfo.Buyer = thisinfo.Buyer
  347. set["buyer"] = thisinfo.Buyer
  348. pInfo.Buyerclass = thisinfo.Buyerclass
  349. set["buyerclass"] = thisinfo.Buyerclass
  350. }
  351. if pInfo.Buyer == "" {
  352. set["buyerclass"] = ""
  353. }
  354. //8--代理机构
  355. if (pInfo.Agency == "" && thisinfo.Agency != "") || (len([]rune(pInfo.Agency)) < 5 && len([]rune(thisinfo.Agency)) > 5) {
  356. pInfo.Agency = thisinfo.Agency
  357. set["agency"] = thisinfo.Agency
  358. }
  359. //9--采购单位联系人
  360. if thisinfo.Buyerperson != "" && strings.Index(pInfo.Buyerperson, thisinfo.Buyerperson) < 0 {
  361. pInfo.Buyerperson = thisinfo.Buyerperson
  362. set["buyerperson"] = pInfo.Buyerperson
  363. }
  364. //10--采购单位電話
  365. if thisinfo.Buyertel != "" && strings.Index(pInfo.Buyertel, thisinfo.Buyertel) < 0 {
  366. pInfo.Buyertel = thisinfo.Buyertel
  367. set["buyertel"] = pInfo.Buyertel
  368. }
  369. if thisinfo.Bidopentime > pInfo.Bidopentime {
  370. pInfo.Bidopentime = thisinfo.Bidopentime
  371. set["bidopentime"] = pInfo.Bidopentime
  372. }
  373. //废标、流标 处理时间
  374. if thisinfo.SubType == "流标" || thisinfo.SubType == "废标" {
  375. pInfo.FirstTime = thisinfo.Publishtime
  376. pInfo.Bidopentime = int64(0)
  377. pInfo.LastTime = thisinfo.Publishtime
  378. set["firsttime"] = thisinfo.Publishtime
  379. set["zbtime"] = int64(0)
  380. set["publishtime"] = thisinfo.Publishtime
  381. set["bidopentime"] = int64(0)
  382. }
  383. if len(thisinfo.Topscopeclass) > 0 {
  384. sort.Strings(pInfo.Topscopeclass)
  385. for _, k := range thisinfo.Topscopeclass {
  386. if BinarySearch(pInfo.Topscopeclass, k) == -1 {
  387. pInfo.Topscopeclass = append(pInfo.Topscopeclass, k)
  388. sort.Strings(pInfo.Topscopeclass)
  389. }
  390. }
  391. set["topscopeclass"] = pInfo.Topscopeclass
  392. }
  393. if len(thisinfo.Subscopeclass) > 0 {
  394. sort.Strings(pInfo.Subscopeclass)
  395. for _, k := range thisinfo.Subscopeclass {
  396. if BinarySearch(pInfo.Subscopeclass, k) == -1 {
  397. pInfo.Subscopeclass = append(pInfo.Subscopeclass, k)
  398. sort.Strings(pInfo.Subscopeclass)
  399. }
  400. }
  401. set["subscopeclass"] = pInfo.Subscopeclass
  402. set["s_subscopeclass"] = strings.Join(pInfo.Subscopeclass, ",")
  403. }
  404. //winner
  405. if len(thisinfo.Winners) > 0 {
  406. sort.Strings(pInfo.Winners)
  407. for _, k := range thisinfo.Winners {
  408. if BinarySearch(pInfo.Winners, k) == -1 {
  409. pInfo.Winners = append(pInfo.Winners, k)
  410. sort.Strings(pInfo.Winners)
  411. }
  412. }
  413. //set["winners"] = pInfo.Winners
  414. set["s_winner"] = strings.Join(pInfo.Winners, ",")
  415. }
  416. if thisinfo.HasPackage {
  417. pkg := PackageFormat(thisinfo, pInfo)
  418. set["multipackage"] = 1
  419. pInfo.Package = pkg
  420. }else {
  421. set["multipackage"] = 0
  422. }
  423. //处理多包后,计算预算金额、中标金额
  424. CountAmount(pInfo, thisinfo)
  425. set["budget"] = pInfo.Budget
  426. set["bidamount"] = pInfo.Bidamount
  427. set["mpn"] = pInfo.MPN
  428. set["mpc"] = pInfo.MPC
  429. set["pici"] = p.pici
  430. return set
  431. }
  432. func deleteSlice1(arr []interface{}, v interface{}) []interface{} {
  433. for k, v1 := range arr {
  434. if reflect.DeepEqual(v1, v) {
  435. return append(arr[:k], arr[k+1:]...)
  436. }
  437. }
  438. return arr
  439. }
  440. func updateValue(info map[string]interface{}, tmp map[string]interface{}) map[string]interface{} {
  441. for k := range info{
  442. for k1 := range tmp {
  443. if k == k1 && info[k] != tmp[k1] {
  444. info[k] = tmp[k]
  445. break
  446. }
  447. }
  448. }
  449. return info
  450. }
  451. //备份(快照)
  452. func backupPro(tmp map[string]interface{}) {
  453. tmp1 := make(map[string]interface{})
  454. for k, v := range tmp{
  455. tmp1[k] = v
  456. }
  457. if Sysconfig["backupFlag"].(bool) {
  458. tmp1["sourceprojectid"] = tmp1["_id"]
  459. delete(tmp1, "_id")
  460. MongoTool.Save(BackupColl, tmp1)
  461. }
  462. }