shandong_common.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. * @Descripttion: 山东导入接口(原始内容参考中山)
  3. * @Author: Tony
  4. * @Date: 2022-10-09
  5. */
  6. INTERFACE_IMPORT = (() => {
  7. 'use strict';
  8. /**
  9. *
  10. * @param {String} areaKey - 地区标识,如:'安徽@马鞍山',有些地区的接口只是取值上有不同,共有一个接口脚本, 需要通过地区标识确定一些特殊处理
  11. * @param {Object} xmlObj - xml经过x2js转换后的xml对象
  12. * @return {Object} - 返回的格式需要统一,具体参考函数内返回的内容。返回的内容会经过一系列的统一处理形成可入库的数据。
  13. */
  14. const RoadGradeMap = {
  15. "0": "高速公路",
  16. "1": "一级公路",
  17. "2": "二级公路",
  18. "3": "三级公路",
  19. "4": "四级公路",
  20. "5": "等外公路",
  21. "6": "独立桥梁",
  22. "7":"独立隧道"
  23. }
  24. function formateDataString(dstring) {
  25. if (!dstring || dstring == "") return "";
  26. const strArr = dstring.split("T");
  27. return strArr[0]
  28. }
  29. async function entry(areaKey, xmlObj) {
  30. const {
  31. UTIL: {
  32. getValue,
  33. arrayValue,
  34. getBool,
  35. extractItemsRecur,
  36. }
  37. } = INTERFACE_EXPORT_BASE;
  38. let info = [];
  39. let tenders = [];
  40. let CprjInfo = getValue(xmlObj, ['CprjInfo']);
  41. let EprjInfos = arrayValue(CprjInfo, ["EprjInfo"]);
  42. if (EprjInfos.length > 0) {
  43. let MakeInfo = EprjInfos[0].MakeInfo;
  44. let Params = EprjInfos[0].Params;
  45. let BuildType = getValue(Params, ['_BuildType']);
  46. let natureConstruction = "";
  47. if (BuildType == "0") natureConstruction = "新建";
  48. if (BuildType == "1") natureConstruction = "改扩建";
  49. let terrainCategory = "";
  50. let Terrain = getValue(Params, ['_Terrain']);
  51. if (Terrain == "0") terrainCategory = "平原微丘";
  52. if (Terrain == "1") terrainCategory = "山岭重丘";
  53. let RoadGrade = getValue(Params, ['_RoadGrade']);
  54. let roadGrade = "";
  55. if (RoadGradeMap[RoadGrade]) roadGrade = RoadGradeMap[RoadGrade];
  56. info = [
  57. { key: 'constructingUnit', value: getValue(MakeInfo, ['_Manage']) },
  58. { key: 'designUnit', value: getValue(MakeInfo, ['_Designer']) },
  59. { key: 'compileUnit', value: getValue(MakeInfo, ['_Compile']) },
  60. { key: 'compileApprover', value: getValue(MakeInfo, ['_CompileApprover']) },
  61. { key: 'compileCertNo', value: getValue(MakeInfo, ['_CompileCertNo']) },
  62. { key: 'compileDate', value: formateDataString(getValue(MakeInfo, ['_CompileDate'])) },
  63. { key: 'reviewUnit', value: getValue(MakeInfo, ['_Review']) },
  64. { key: 'reviewApprover', value: getValue(MakeInfo, ['_ReviewApprover']) },
  65. { key: 'reviewCertNo', value: getValue(MakeInfo, ['_ReviewCertNo']) },
  66. { key: 'reviewDate', value: formateDataString(getValue(MakeInfo, ['_ReviewDate'])) },
  67. { key: 'startChainages', value: getValue(Params, ['_StartPileNo'])},
  68. { key: 'endChainages', value: getValue(Params, ['_EndPileNo']) },
  69. { key: 'location', value: getValue(Params, ['_PrjArea']) },
  70. { key: 'natureConstruction', value: natureConstruction },
  71. { key: 'terrainCategory', value: terrainCategory },
  72. { key: 'roadGrade', value: roadGrade },
  73. { key: 'makeDate', value: getValue(CprjInfo, ['SystemInfo','_MakeDate']) },
  74. ]
  75. for (let t of EprjInfos) {
  76. tenders.push(setupTender(t))
  77. }
  78. }
  79. function setupTender(EprjInfo) {
  80. let tender = {};
  81. let Params = EprjInfo.Params;
  82. let SummaryOfCost = EprjInfo.SummaryOfCost;
  83. tender.name = EprjInfo._Name;
  84. tender.bills = [];
  85. tender.bidEvaluationList = [];
  86. tender.evaluationList = [];
  87. let ProvisionalSums = getValue(SummaryOfCost, ['_ProvisionalSums']);
  88. let Structure = getValue(Params, ['_Structure']);
  89. let pavementStructure = "";
  90. if (Structure == "0") pavementStructure = "沥青路面";
  91. if (Structure == "1") pavementStructure = "水泥混凝土路面";
  92. if (Structure == "2") pavementStructure = "其他类型路面";
  93. tender.feature = [
  94. { key: 'tenderSumLimit', value: getValue(SummaryOfCost, ['_TenderSumLimit'])},//招标控制价
  95. { key: 'designSpeed', value: getValue(Params, ['_DesignSpeed']) },// --todo
  96. { key: 'pavementStructure', value: pavementStructure},// --todo
  97. { key: 'subgradeWidth', value: getValue(Params, ['_SubgradeWidth']) },
  98. { key: 'roadLength', value: getValue(Params, ['_RoadLength']) },// --todo
  99. { key: 'bridgeLength', value: getValue(Params, ['_BridgeLength']) },
  100. { key: 'tunnelLength', value: getValue(Params, ['_TunnelLength']) },// --todo
  101. { key: 'briTunRate', value: getValue(Params, ['_BriTunRate']) },// --todo
  102. { key: 'interchangeNum', value: getValue(Params, ['_InterchangeNum']) },// --todo
  103. { key: 'stubLengths', value: getValue(Params, ['_StubLengths']) },// --todo
  104. { key: 'laneLength', value: getValue(Params, ['_LaneLength']) },// --todo
  105. ]
  106. const items = arrayValue(EprjInfo, ['Items', 'Item']);
  107. let hasOneHundredChapter = false;
  108. for (let i of items) {
  109. let bill = setupBills(i);
  110. if (bill.name.indexOf('第100章') >= 0 && bill.name.indexOf('总则') >= 0) hasOneHundredChapter = true;
  111. if (bill.name == "暂列金额(不含计日工总额)") {
  112. bill.fees = [{ fieldName: "common",tenderTotalFee:ProvisionalSums, tenderUnitFee: "0", totalFee: ProvisionalSums, unitFee: "0" }];
  113. if (bill.calcBase === undefined || bill.calcBase === null || bill.calcBase === '') {
  114. // 正常导入的暂列金额应该有公式(山东特有),没有公式再导ProvisionalSums
  115. bill.calcBase = ProvisionalSums;
  116. }
  117. bill.calcFlag = 1;
  118. }
  119. let formula = getValue(i, ['CostComposition', 'Formula', '_Formulas']);
  120. if (formula !== undefined && formula !== null && formula !== '') {
  121. bill.exCalcStr = formula; // 不仅仅'投标报价'有,其他的也要
  122. }
  123. // if (bill.name == '投标报价') {
  124. // bill.exCalcStr = formula || '';
  125. // }
  126. tender.bills.push(bill);
  127. }
  128. tender.hasOneHundredChapter = hasOneHundredChapter;
  129. // 山东的 formula 还得调整
  130. // setupFormula(tender.bills);
  131. const BidEvaluationMainMaterial = arrayValue(EprjInfo, ['BidEvaluationMainMaterial']);
  132. for (let b of BidEvaluationMainMaterial) {
  133. tender.bidEvaluationList.push(setUpBidEvaluation(b))
  134. }
  135. return tender;
  136. }
  137. function handleBillPrice(bill, formula, totalFee, quantity) {
  138. if (formula) {
  139. bill.calcFlag = 1;
  140. bill.exCalcStr = formula;
  141. } else if (!formula && !quantity && totalFee) {
  142. // 没有基数、没有工程量时,有金额时,金额作为基数
  143. bill.exCalcStr = String(totalFee);
  144. bill.calcFlag = 1;
  145. } else {
  146. bill.calcFlag = 2;
  147. }
  148. }
  149. function setupBills(item, needClac = false) {
  150. const regBlank = new RegExp(' ', 'g');
  151. let bill = {
  152. code: item._ListCode,
  153. name: item._ListName,
  154. unit: item._Unit,
  155. quantity: item._Num,
  156. remark: item._Remarks,
  157. jobContentText: item._Content,
  158. specialProvisional: '',
  159. formulaCode: item._FormulaCode,
  160. qtyFormula: item._QtyFormula,
  161. children: []
  162. }
  163. const formula = getValue(item, ['CostComposition', 'Formula', '_Formulas']);
  164. // if ((needClac || bill.name == "暂列金额(不含计日工总额)") && bill.qtyFormula && bill.qtyFormula !== '') {
  165. if ((needClac || bill.name == "暂列金额(不含计日工总额)") && bill.hasOwnProperty('qtyFormula')) {
  166. let formula = getValue(item, ['CostComposition', 'Formula', '_Formulas']);
  167. let ratio = getValue(item, ['CostComposition', 'Formula', '_Ratio']);
  168. if (formula !== undefined && formula !== null && formula !== '') {
  169. bill.calcBase = formula; // 这个formula在后期还要处理的
  170. if (ratio && ratio !== '') {
  171. let dRation = parseFloat(ratio);
  172. if (!isNaN(dRation) && dRation != 1) {
  173. bill.calcBase = `(${formula}) * ${dRation}`; // 如果有费率且不等于1,还需要调整基数公式
  174. }
  175. }
  176. }
  177. }
  178. if (item._ProvisionalType == '0') bill.specialProvisional = '材料暂估';
  179. if (item._ProvisionalType == '1') bill.specialProvisional = '工程设备';
  180. if (item._ProvisionalType == '2') bill.specialProvisional = '专业工程';
  181. if (item._ProvisionalType == '3') bill.specialProvisional = '固定费用';
  182. if (item._ProvisionalType == '2') {
  183. let sumVal = getValue(item, ['_Sum']);
  184. let priceVal = getValue(item, ['_Price']);
  185. bill.fees = [{ fieldName: "common",tenderTotalFee:sumVal, tenderUnitFee: priceVal, totalFee: sumVal, unitFee: priceVal }];
  186. // bill.calcBase = sumVal;
  187. // bill.calcFlag = 2;
  188. handleBillPrice(bill, formula, +sumVal, +bill.quantity);
  189. }
  190. if (item._ProvisionalType == '3') {
  191. let sumVal = getValue(item, ['_Sum']);
  192. let priceVal = getValue(item, ['_Price']);
  193. // if ((+sumVal) < (+priceVal)) sumVal = priceVal;
  194. bill.fees = [{ fieldName: "common",tenderTotalFee:sumVal, tenderUnitFee: priceVal, totalFee: sumVal, unitFee: priceVal }];
  195. // bill.calcBase = sumVal;
  196. // bill.calcFlag = 2;
  197. handleBillPrice(bill, formula, +sumVal, +bill.quantity);
  198. }
  199. let subItems = arrayValue(item, ['Item']);
  200. if (subItems && subItems.length > 0) {
  201. for (let i of subItems) {
  202. if (typeof i._ListName === 'string' && i._ListName.replace(regBlank, '') === '清单第100章总则') {
  203. bill.children.push(setupBills(i, true));
  204. } else {
  205. bill.children.push(setupBills(i, needClac));
  206. }
  207. }
  208. }
  209. return bill;
  210. }
  211. function setUpBidEvaluation(b) {
  212. return {
  213. seq: b._Code,
  214. code: b._Number,
  215. name: b._Name,
  216. specs: b._Specification,
  217. unit: b._Unit,
  218. market_price: b._Price,
  219. quantity: b._Quantity,
  220. remark:b._Remark
  221. }
  222. }
  223. return {
  224. name: CprjInfo._CprjName,
  225. info,
  226. tenders,
  227. };
  228. }
  229. async function handleAfterImport(importData) {
  230. function setupFormula(bills) {
  231. const cacheObj = {};
  232. const calcBills = [];
  233. function _transform(calc) {
  234. let rst = calc, tmpCalc = calc;
  235. let calcKeys = [], calcValues = [];
  236. let preIdx = tmpCalc.indexOf('{');
  237. while (preIdx >= 0) {
  238. let rearIdx = tmpCalc.indexOf('}');
  239. if (rearIdx > preIdx) {
  240. let fnStr = tmpCalc.substring(preIdx + 1, rearIdx);
  241. if (cacheObj[fnStr]) {
  242. calcKeys.push(`{${fnStr}}`);
  243. calcValues.push(`@${cacheObj[fnStr].ID}`);
  244. }
  245. tmpCalc = tmpCalc.substr(rearIdx + 1);
  246. preIdx = tmpCalc.indexOf('{');
  247. } else {
  248. //有异常了
  249. break;
  250. }
  251. }
  252. if (calcKeys.length > 0) {
  253. calcKeys.forEach((key, index)=> {
  254. rst = rst.replace(key, calcValues[index]);
  255. });
  256. }
  257. return rst;
  258. }
  259. //1. 先把有formulaCode的清单cache起来
  260. //2. 顺带过滤出有calcBase的清单
  261. for (let bill of bills) {
  262. if (typeof bill.formulaCode === 'string' && bill.formulaCode.indexOf('F') === 0) {
  263. cacheObj[bill.formulaCode] = bill;
  264. }
  265. if (typeof bill.calcBase === 'string' && bill.calcBase.length > 0) {
  266. if (bill.exCalcStr) bill.calcBase = bill.exCalcStr;
  267. calcBills.push(bill);
  268. } else if (bill.exCalcStr) {
  269. bill.calcBase = bill.exCalcStr;
  270. calcBills.push(bill);
  271. }
  272. }
  273. //3. Action!
  274. for (let calcBill of calcBills) {
  275. calcBill.calcBase = _transform(calcBill.calcBase);
  276. }
  277. }
  278. importData.tenders.forEach((tender, index) => {
  279. setupFormula(tender.bills);
  280. if (!tender.hasOneHundredChapter) {
  281. for (let idx = tender.bills.length - 1; idx >= 0; idx--) {
  282. const bName = tender.bills[idx].name || '';
  283. if (bName.indexOf('第100章') >= 0 && bName.indexOf('总则') > 0) {
  284. tender.bills.splice(idx, 1);
  285. break;
  286. }
  287. }
  288. }
  289. delete tender.hasOneHundredChapter;
  290. });
  291. }
  292. return {
  293. entry,
  294. handleAfterImport,
  295. };
  296. })();