package main import ( "github.com/go-xweb/log" "go.mongodb.org/mongo-driver/bson/primitive" "math" qu "qfw/util" "reflect" "sort" "strings" ) func (p *ProjectTask) modifyUpdate(pInfoId string, index int, info *Info, tmp map[string]interface{}, tmpPro map[string]interface{}, modifyMap map[string]interface{}) { backupPro(tmpPro) infoList := []interface{}(tmpPro["list"].(primitive.A)) infoMap := infoList[index].(map[string]interface{}) infoList[index] = updateValue(infoMap, modifyMap) infofiled := InfoField{ Budget: info.Budget, Bidamount: info.Bidamount, ContractCode: info.ContractCode, ProjectName: info.ProjectName, ProjectCode: info.ProjectCode, Bidstatus: info.SubType, } mapTmp, _ := tmpPro["infofiled"].(map[string]interface{}) mapTmp[info.Id] = StructToMap(infofiled) set := map[string]interface{}{ "$set": tmpPro, } _ = MongoTool.UpdateById(ProjectColl, pInfoId, set) } func (p *ProjectTask) mergeAndModify(pInfoId string, index int, info *Info, tmp map[string]interface{}, tmpPro map[string]interface{}, modifyMap map[string]interface{}) { p.AllIdsMapLock.Lock() currentPro := p.AllIdsMap[pInfoId] p.AllIdsMapLock.Unlock() merge, pId, i, comStr, mergePro := p.updateMerge(index, info, pInfoId, tmp, tmpPro) //招标信息在list中第1个 if index == 0 { log.Println("第1条合并", "------1------") //快照 backupPro(tmpPro) p.AllIdsMapLock.Lock() delete(p.AllIdsMap, pInfoId) p.AllIdsMapLock.Unlock() count := MongoTool.Delete(ProjectColl, pInfoId) log.Println(count) for _, infoId := range currentPro.P.Ids{ if infoId == info.Id { continue } tmp1 := MongoTool.FindById(ExtractColl, infoId) p.fillInPlace(tmp) info1 := ParseInfo(tmp1) p.CommonMerge(tmp1, info1) } }else { log.Println("第n条合并", "------n------") //快照 招标信息所在的项目 backupPro(tmpPro) if merge { //跟原项目list第0条信息作对比,可以合并 if pId == pInfoId { //合并到当前项目 mergeProject(p, currentPro.P, info, tmpPro, index) p.AllIdsMapLock.Lock() p.AllIdsMap[currentPro.P.Id.Hex()].P = currentPro.P p.AllIdsMapLock.Unlock() infoList := []interface{}(tmpPro["list"].(primitive.A)) infoMap := infoList[index].(map[string]interface{}) infoList[index] = updateValue(infoMap, modifyMap) infofiled := InfoField{ Budget: info.Budget, Bidamount: info.Bidamount, ContractCode: info.ContractCode, ProjectName: info.ProjectName, ProjectCode: info.ProjectCode, Bidstatus: info.SubType, } mapTmp, _ := tmpPro["infofiled"].(map[string]interface{}) mapTmp[info.Id] = StructToMap(infofiled) set := map[string]interface{}{ "$set": tmpPro, } MongoTool.UpdateById(ProjectColl, pInfoId, set) }else { //合并到的其它项目里边 //更新其它的项目 pro := MongoTool.FindById(ProjectColl, mergePro.Id.Hex()) backupPro(pro) choose, ex := p.CompareStatus(mergePro, info) if !choose { p.UpdateProject(tmp, info, mergePro, i, comStr, ex) }else { id, p1 := p.NewProject(tmp, info) p.AllIdsMapLock.Lock() p.AllIdsMap[id] = &ID{Id: id, P: p1} p.AllIdsMapLock.Unlock() } //内部合并 p.innerMerge(currentPro.P, info, tmp, tmpPro) } }else { //合并到新建的项目里边,原有项目内部合并 p.innerMerge(currentPro.P, info, tmp, tmpPro) } } } func (p *ProjectTask) updateMerge(index int, info *Info, pInfoId string, tmp map[string]interface{}, tmpPro map[string]interface{}) (bool, string, int, string, *ProjectInfo) { bpn, bpc, bptc, bpb, pids, _, IDArr := p.getCompareIds(info.ProjectName, info.ProjectCode, info.PTC, info.Buyer) defer p.wg.Done() for _, m := range pids { defer m.Lock.Unlock() } for _, id := range IDArr { defer id.Lock.Unlock() } bFindProject := false findPid := "" //获取完id,进行计算 //定义两组 comRes1 := []*ProjectInfo{} //优先级最高的对比结果数组 comRes2 := []*ProjectInfo{} //优化级其次 comRes3 := []*ProjectInfo{} for _, v := range IDArr { if index == 0 && pInfoId == v.P.Id.Hex() { //招标条目信息在原项目中是第0条时,忽略 continue } comStr := "" compareProject := v.P compareProject.score = 0 diffTime := int64(math.Abs(float64(info.Publishtime - compareProject.LastTime))) if diffTime <= p.validTime { //代理机构完全不相同,直接新建项目 if CheckContain(compareProject.Agency, info.Agency) == 3 { continue } //地区(省、市、区)不同,直接新建项目 if ComparePlace(compareProject, info) { continue } info.PNBH = 0 info.PCBH = 0 info.PTCBH = 0 compareStr, score := comparePNC(info, compareProject) resVal, pjVal := Select(compareStr, info, compareProject) if resVal > 0 { compareBuyer, compareCity, compareTime, compareAgency, compareBudget, compareBidmount, score2 := p.compareBCTABB(info, compareProject, diffTime, score) //项目名称、项目编号、标题项目编号、采购单位、省、市、发布时间、代理机构 comStr = compareStr + compareBuyer + compareCity + compareTime + compareAgency + compareBudget + compareBidmount compareProject.comStr = comStr compareProject.pjVal = pjVal compareProject.resVal = resVal eqV := compareResult(resVal, pjVal, score2, comStr, compareBuyer, compareCity, compareTime, compareAgency, compareBudget, compareBidmount) if eqV == 1 { comRes1 = append(comRes1, compareProject) } else if eqV == 2 { comRes2 = append(comRes2, compareProject) } else if eqV == 3 { comRes3 = append(comRes3, compareProject) } } } } //--------------------------------对比完成----------------------- k := -1 comStr := "" mergePro := &ProjectInfo{} for kv, resN := range [][]*ProjectInfo{comRes1, comRes2, comRes3} { if len(resN) > 0 { if len(resN) > 1 { sort.Slice(resN, func(i, j int) bool { return resN[i].score > resN[j].score }) } ex := 0 resArr := []*ProjectInfo{} for _, res := range resN{ choose, e := p.CompareStatus(resN[0], info) if !choose { ex = e resArr = append(resArr, res) } } if len(resArr) > 0 { bFindProject = true findPid = resArr[0].Id.Hex() for k2, bv := range []int{bpn, bpc, bptc, bpb} { if bv > -1 { pids[bv].Arr = append(pids[bv].Arr, findPid) if k2 == 0 { if resArr[0].ProjectName == "" { resArr[0].ProjectName = info.ProjectName } else { if resArr[0].MPN == nil { resArr[0].MPN = []string{info.ProjectName} } else { resArr[0].MPN = append(resArr[0].MPN, info.ProjectName) } } } else if k2 < 3 { if resArr[0].ProjectCode == "" { resArr[0].ProjectCode = qu.If(k2 == 1, info.ProjectCode, info.PTC).(string) } else { if resArr[0].MPC == nil { resArr[0].MPC = []string{qu.If(k2 == 1, info.ProjectCode, info.PTC).(string)} } else { resArr[0].MPC = append(resArr[0].MPC, qu.If(k2 == 1, info.ProjectCode, info.PTC).(string)) } } } else { if resArr[0].Buyer == "" { resArr[0].Buyer = info.Buyer } } } } if index != 0 { //招标条目信息在原项目中是第非0条时,返回对比结果 k = kv+1 comStr = resArr[0].comStr mergePro = resArr[0] bFindProject = false findPid = "" }else { mergePro = resArr[0] //如果有合并,合并之前备份(快照) backupPro(tmpPro) p.UpdateProject(tmp, info, resArr[0], kv+1, resArr[0].comStr, ex) } }else { bFindProject = false findPid = "" } break } } if !bFindProject { id, p1 := p.NewProject(tmp, info) p.AllIdsMapLock.Lock() p.AllIdsMap[id] = &ID{Id: id, P: p1} p.AllIdsMapLock.Unlock() for _, m := range pids { m.Arr = append(m.Arr, id) } } return bFindProject, findPid, k, comStr, mergePro } //内部合并 func (p *ProjectTask) innerMerge(pInfo *ProjectInfo, info *Info, tmp map[string]interface{}, tmpPro map[string]interface{}) { infoList := []interface{}(tmpPro["list"].(primitive.A)) for index, info1 := range infoList{ info2 := info1.(map[string]interface{}) if info2["infoid"] == info.Id { deleteSlice1(infoList, info1) continue } mergeProject(p, pInfo, info, tmpPro, index) } mapTmp, _ := tmpPro["infofiled"].(map[string]interface{}) delete(mapTmp, info.Id) set := map[string]interface{}{ "$set": tmpPro, } MongoTool.UpdateById(ProjectColl, pInfo.Id.Hex(), set) } //合并字段到project func mergeProject(p *ProjectTask, pInfo *ProjectInfo, thisinfo *Info, set map[string]interface{}, index int) map[string]interface{} { //1--firsttime if thisinfo.Publishtime < pInfo.FirstTime && thisinfo.Publishtime > 0 { pInfo.FirstTime = thisinfo.Publishtime set["firsttime"] = thisinfo.Publishtime if thisinfo.TopType == "招标" { set["zbtime"] = thisinfo.Publishtime } } //2--lasttime pInfo.LastTime = thisinfo.Publishtime set["lasttime"] = thisinfo.Publishtime if thisinfo.TopType == "招标" { set["zbtime"] = thisinfo.Publishtime } else if thisinfo.TopType == "结果" || thisinfo.SubType == "合同" { set["jgtime"] = thisinfo.Publishtime } //废标、流标 处理时间 if thisinfo.SubType == "流标" || thisinfo.SubType == "废标" { pInfo.FirstTime = thisinfo.Publishtime pInfo.Bidopentime = int64(0) pInfo.LastTime = thisinfo.Publishtime set["firsttime"] = thisinfo.Publishtime set["zbtime"] = int64(0) set["publishtime"] = thisinfo.Publishtime set["bidopentime"] = int64(0) } bt := thisinfo.TopType bs := thisinfo.SubType p.mapBidLock.Lock() if bt == "招标" { //招标状态,更新projectscope if thisinfo.ProjectScope != "" { set["projectscope"] = thisinfo.ProjectScope } set["bidtype"] = bidtype[bs] }else { set["bidtype"] = bt if bidstatus[bs] != "" { set["bidstatus"] = thisinfo.SubType } else if thisinfo.Infoformat == 2 { set["bidstatus"] = "拟建" } else { set["bidstatus"] = "其它" } } p.mapBidLock.Unlock() //3\4\5--省、市、县 if thisinfo.Area != "全国" { //xt := true if pInfo.Area == "全国" { pInfo.Area = thisinfo.Area set["area"] = thisinfo.Area } else if pInfo.Area != thisinfo.Area { //xt = false } if pInfo.City == "" && thisinfo.City != "" { pInfo.City = thisinfo.City set["city"] = thisinfo.City } else if pInfo.City != thisinfo.City { //xt = false } if thisinfo.District != "" && pInfo.District == "" { pInfo.District = thisinfo.District set["district"] = thisinfo.District } } //6--项目名称 if (thisinfo.ProjectName != "" && pInfo.ProjectName == "") || (len([]rune(pInfo.ProjectName)) < 6 && thisinfo.LenPN > 6) { pInfo.ProjectName = thisinfo.ProjectName set["projectname"] = thisinfo.ProjectName } //7--项目编号 if (pInfo.ProjectCode == "" && thisinfo.ProjectCode != "") || (len([]rune(pInfo.ProjectCode)) < 6 && len([]rune(thisinfo.ProjectCode)) > 6) { pInfo.ProjectCode = thisinfo.ProjectCode set["projectcode"] = thisinfo.ProjectCode } //7--采购单位 if (pInfo.Buyer == "" && thisinfo.Buyer != "") || (len([]rune(pInfo.Buyer)) < 5 && len([]rune(thisinfo.Buyer)) > 5) { pInfo.Buyer = thisinfo.Buyer set["buyer"] = thisinfo.Buyer pInfo.Buyerclass = thisinfo.Buyerclass set["buyerclass"] = thisinfo.Buyerclass } if pInfo.Buyer == "" { set["buyerclass"] = "" } //8--代理机构 if (pInfo.Agency == "" && thisinfo.Agency != "") || (len([]rune(pInfo.Agency)) < 5 && len([]rune(thisinfo.Agency)) > 5) { pInfo.Agency = thisinfo.Agency set["agency"] = thisinfo.Agency } //9--采购单位联系人 if thisinfo.Buyerperson != "" && strings.Index(pInfo.Buyerperson, thisinfo.Buyerperson) < 0 { pInfo.Buyerperson = thisinfo.Buyerperson set["buyerperson"] = pInfo.Buyerperson } //10--采购单位電話 if thisinfo.Buyertel != "" && strings.Index(pInfo.Buyertel, thisinfo.Buyertel) < 0 { pInfo.Buyertel = thisinfo.Buyertel set["buyertel"] = pInfo.Buyertel } if thisinfo.Bidopentime > pInfo.Bidopentime { pInfo.Bidopentime = thisinfo.Bidopentime set["bidopentime"] = pInfo.Bidopentime } //废标、流标 处理时间 if thisinfo.SubType == "流标" || thisinfo.SubType == "废标" { pInfo.FirstTime = thisinfo.Publishtime pInfo.Bidopentime = int64(0) pInfo.LastTime = thisinfo.Publishtime set["firsttime"] = thisinfo.Publishtime set["zbtime"] = int64(0) set["publishtime"] = thisinfo.Publishtime set["bidopentime"] = int64(0) } if len(thisinfo.Topscopeclass) > 0 { sort.Strings(pInfo.Topscopeclass) for _, k := range thisinfo.Topscopeclass { if BinarySearch(pInfo.Topscopeclass, k) == -1 { pInfo.Topscopeclass = append(pInfo.Topscopeclass, k) sort.Strings(pInfo.Topscopeclass) } } set["topscopeclass"] = pInfo.Topscopeclass } if len(thisinfo.Subscopeclass) > 0 { sort.Strings(pInfo.Subscopeclass) for _, k := range thisinfo.Subscopeclass { if BinarySearch(pInfo.Subscopeclass, k) == -1 { pInfo.Subscopeclass = append(pInfo.Subscopeclass, k) sort.Strings(pInfo.Subscopeclass) } } set["subscopeclass"] = pInfo.Subscopeclass set["s_subscopeclass"] = strings.Join(pInfo.Subscopeclass, ",") } //winner if len(thisinfo.Winners) > 0 { sort.Strings(pInfo.Winners) for _, k := range thisinfo.Winners { if BinarySearch(pInfo.Winners, k) == -1 { pInfo.Winners = append(pInfo.Winners, k) sort.Strings(pInfo.Winners) } } //set["winners"] = pInfo.Winners set["s_winner"] = strings.Join(pInfo.Winners, ",") } if thisinfo.HasPackage { pkg := PackageFormat(thisinfo, pInfo) set["multipackage"] = 1 pInfo.Package = pkg }else { set["multipackage"] = 0 } //处理多包后,计算预算金额、中标金额 CountAmount(pInfo, thisinfo) set["budget"] = pInfo.Budget set["bidamount"] = pInfo.Bidamount set["mpn"] = pInfo.MPN set["mpc"] = pInfo.MPC set["pici"] = p.pici return set } func deleteSlice1(arr []interface{}, v interface{}) []interface{} { for k, v1 := range arr { if reflect.DeepEqual(v1, v) { return append(arr[:k], arr[k+1:]...) } } return arr } func updateValue(info map[string]interface{}, tmp map[string]interface{}) map[string]interface{} { for k := range info{ for k1 := range tmp { if k == k1 && info[k] != tmp[k1] { info[k] = tmp[k] break } } } return info } //备份(快照) func backupPro(tmp map[string]interface{}) { tmp1 := make(map[string]interface{}) for k, v := range tmp{ tmp1[k] = v } if Sysconfig["backupFlag"].(bool) { tmp1["sourceprojectid"] = tmp1["_id"] delete(tmp1, "_id") MongoTool.Save(BackupColl, tmp1) } }