info_price_facade.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /**
  2. * Created by zhang on 2020/7/20
  3. */
  4. module.exports={
  5. getOptions,
  6. getDataByCondition,
  7. getClassByAreaID,
  8. mutiApplyInfoPrice
  9. };
  10. const mongoose = require('mongoose');
  11. let infoLibModel = mongoose.model("std_price_info_lib");
  12. let infoClassModel = mongoose.model("std_price_info_class");
  13. let infoItemsModel = mongoose.model("std_price_info_items");
  14. let infoAreasModel = mongoose.model("std_price_info_areas");
  15. let unitPriceModel = mongoose.model("unit_price");
  16. let _ = require("lodash");
  17. let gljUtil = require('../../../public/web/gljUtil');
  18. const scMathUtil = require('../../../public/scMathUtil').getUtil();
  19. let projectfacade = require('./project_facade');
  20. // 载入模块
  21. var Segment = require('segment');
  22. // 创建实例
  23. var segment = new Segment();
  24. // 使用默认的识别模块及字典,载入字典文件需要1秒,仅初始化时执行一次即可
  25. segment.useDefault();
  26. async function getOptions(data,compilation){//data 是预留对象,暂时不用
  27. let compilationID = compilation._id;
  28. let areaMap={};
  29. let periodMap={};
  30. let areas =await infoAreasModel.find({"compilationID":compilationID}).lean();
  31. let libList = await infoLibModel.find({"compilationID":compilationID}).lean();
  32. for(let l of libList){
  33. // for(let area of l.areas){
  34. // if(!areaMap[area]) areas.push(area);
  35. // }
  36. //2020-05
  37. let periodArray = l.period.split("-");
  38. periodMap[periodArray[0]]?periodMap[periodArray[0]].push(periodArray[1]):periodMap[periodArray[0]]=[periodArray[1]]
  39. }
  40. for(let key in periodMap){
  41. periodMap[key] = _.sortBy(periodMap[key]);
  42. }
  43. return {areas:areas,periodMap:periodMap}
  44. }
  45. async function getClassByAreaID(data,compilation){
  46. console.log(data);
  47. //要先知道根据期数和编办查找库ID
  48. let newList = [];
  49. let lib = await infoLibModel.findOne({compilationID:compilation._id,period:data.period})
  50. if(lib){
  51. let tList =await getClassList(data.areaID,lib.ID);
  52. newList.push(...tList);
  53. if(data.commonInfoPriceID){
  54. cList = await getClassList(data.commonInfoPriceID,lib.ID);
  55. newList.push(...cList);
  56. }
  57. }
  58. async function getClassList(areaID,libID){
  59. let temList = [];
  60. let infoClass = await infoClassModel.find({areaID:areaID,libID:libID}).lean();
  61. let parentMap=_.groupBy(infoClass, 'ParentID');
  62. for(let key in parentMap){
  63. parentMap[key] = projectfacade.sortChildren(parentMap[key]);
  64. }
  65. if(parentMap && parentMap['-1']){
  66. getChildern(parentMap['-1'],temList,parentMap)
  67. }
  68. return temList;
  69. }
  70. function getChildern(children,list,pm){
  71. for(let c of children){
  72. list.push(c);
  73. if(pm[c.ID]){
  74. getChildern(pm[c.ID],list,pm)
  75. }
  76. }
  77. }
  78. return newList;
  79. }
  80. async function getDataByCondition(data,compilation){
  81. let result = {};
  82. data.condition["compilationID"] = compilation._id;
  83. //特殊处理重庆的,地区选择非“通用”时,搜索范围应是当前选择的地区,加上“通用”中的信息价。
  84. if (data.condition.commonInfoPriceID) {
  85. let idArray = [data.condition.areaID,data.condition.commonInfoPriceID];
  86. data.condition.areaID = {$in: idArray}
  87. delete data.condition.commonInfoPriceID;
  88. }
  89. //根据地区+期数+材料编号的前4位与信息价材料的分类编号匹配,如果有数据,则显示数据出来。
  90. //先按编号匹配
  91. if (data.code) {
  92. result = await getDataByCode(data.code, data);
  93. if (result.totalSize > 0) return result;
  94. }
  95. //编号匹配不上的情况:
  96. //有关键字的情况
  97. if (data.keyWord) {
  98. return await getDataByKeyWord(data.keyWord,data);
  99. }
  100. //查询所有的情况
  101. if(data.lastID){ //有最后一行说明是查询下一页
  102. data.condition["_id"] = {$gt:mongoose.Types.ObjectId(data.lastID)};
  103. }else{
  104. result.totalSize = await infoItemsModel.find(data.condition).count();
  105. }
  106. result.items = await infoItemsModel.find(data.condition).lean().sort({"_id":1}).limit(50);
  107. return result;
  108. }
  109. async function getDataByCode(code, data) {
  110. let condition = { ...data.condition };
  111. condition.code = code;
  112. let totalSize = await infoItemsModel.find(condition).count();
  113. if (data.lastID) { //有最后一行说明是查询下一页
  114. condition["_id"] = {$gt:mongoose.Types.ObjectId(data.lastID)};
  115. }
  116. let items = [];
  117. if (totalSize > 0) {
  118. items = await infoItemsModel.find(condition).lean().sort({"_id":1}).limit(50);
  119. }
  120. return {totalSize,items}
  121. }
  122. async function getDataByKeyWord(keyword, data) {
  123. //先按全字匹配
  124. let fullResult =await getDataByFullKeyWord(keyword, data);
  125. if(fullResult.totalSize > 0) return fullResult;
  126. //如果没有才按模糊匹配
  127. return await getDataByFuzzyMatch(keyword, data);
  128. }
  129. //按全关键字匹配
  130. async function getDataByFullKeyWord(keyword, data){
  131. data.condition.name = new RegExp(keyword);
  132. let items = await infoItemsModel.find(data.condition).lean().sort({"_id":1});
  133. delete data.condition.name;
  134. return{totalSize:items.length,items}
  135. }
  136. function handelThreeWord(word){
  137. let arr = [];
  138. getArr(word[0]+word[1],arr);
  139. getArr(word[1]+word[2],arr);
  140. if(arr.length > 0) return arr;
  141. return[word];
  142. function getArr(tem,list){
  143. let nameArray = segment.doSegment(tem, {
  144. simple: true, //不返回词性
  145. stripPunctuation: true //去除标点符号
  146. });
  147. //说明是一个词
  148. if(nameArray.length == 1) list.push(tem)
  149. }
  150. }
  151. //自定义特殊处理
  152. function cusSegment(nameArray,keyword){
  153. let temArr = [];
  154. for (let a of nameArray) {
  155. //混凝土 和 砼 统一认成砼
  156. if (a == "混凝土") a = '砼';
  157. if(a == '砼'||a == '砖' ){
  158. temArr.push(a);
  159. }else if(a.length > 1){
  160. //如果是三个字的词,优先识别成两个字
  161. if(a.length == 3){
  162. let sArr = handelThreeWord(a);
  163. temArr.push(...sArr);
  164. }else{
  165. temArr.push(a);
  166. }
  167. }
  168. }
  169. if (keyword.length == 1 && temArr.length == 0) temArr.push(keyword);
  170. return temArr;
  171. }
  172. //模糊匹配
  173. async function getDataByFuzzyMatch(keyword, data){
  174. let items = [];
  175. let nameArray = [];
  176. if (keyword.length < 3) {
  177. nameArray.push(keyword)
  178. } else {
  179. nameArray = segment.doSegment(keyword, {
  180. simple: true, //不返回词性
  181. stripPunctuation: true //去除标点符号
  182. });
  183. }
  184. //自定义处理
  185. nameArray = cusSegment(nameArray,keyword);
  186. console.log(nameArray);
  187. let allInfoPrice = await infoItemsModel.find(data.condition).lean().sort({"_id":1});
  188. let maxNum = 0;//最大匹配数
  189. let matchMap = {};//匹配储存
  190. for (let info of allInfoPrice) {
  191. //specs
  192. let mstring = info.name + info.spec;
  193. mstring = mstring.replace(/混凝土/g, "砼");
  194. info.mstring = mstring;
  195. let matchCount = 0;
  196. for (let na of nameArray) {
  197. if (mstring.indexOf(na) != -1) {
  198. matchCount++;
  199. }
  200. }
  201. if (matchCount > 0) {
  202. matchMap[matchCount] ? matchMap[matchCount].push(info) : matchMap[matchCount] = [info];
  203. if (matchCount > maxNum) maxNum = matchCount;
  204. }
  205. }
  206. if (maxNum > 0) items = matchMap[maxNum];
  207. totalSize = items.length
  208. //按匹配位置排序 如[ '橡胶', '胶圈', '给水' ] 先显示橡胶
  209. items = _.sortBy(items,(item)=>{
  210. let ms = item.mstring;
  211. for(let i = 0;i < nameArray.length;i ++){
  212. if (ms.indexOf(nameArray[i]) != -1) return i;
  213. }
  214. })
  215. return {totalSize,items}
  216. }
  217. async function mutiApplyInfoPrice(data,compilation){
  218. data.condition["compilationID"] = compilation._id;
  219. let infoPrices = await infoItemsModel.find(data.condition).lean();
  220. let tasks = [];
  221. let projectGLJMap = {};
  222. for(let info of infoPrices){
  223. let index = gljUtil.getIndex(info,["name","specs","unit"]);
  224. if(data.pgljMap[index]){
  225. for(let obj of data.pgljMap[index]){
  226. let infoPrice = gljUtil.getInfoMarketPrice(info,data.taxType);
  227. infoPrice = scMathUtil.roundToString(infoPrice,data.decimal);
  228. let doc = {'market_price':infoPrice,'priceFrom':data.priceFrom};
  229. let task = {
  230. updateOne:{
  231. filter:{'id':obj.unitPriceID},
  232. update:doc
  233. }
  234. };
  235. tasks.push(task);
  236. projectGLJMap[obj.pgljID] = {index:obj.fullIndex,doc:doc};
  237. }
  238. }
  239. }
  240. if(tasks.length > 0) await unitPriceModel.bulkWrite(tasks);
  241. return projectGLJMap;
  242. }