unit_price_model.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /**
  2. * 单价业务模型
  3. *
  4. * @author CaiAoLin
  5. * @date 2017/6/30
  6. * @version
  7. */
  8. import BaseModel from "../../common/base/base_model"
  9. import GLJTypeConst from "../../common/const/glj_type_const"
  10. import CounterModel from "./counter_model"
  11. import MixRatioModel from "./mix_ratio_model";
  12. import {default as UnitPriceSchema, collectionName as collectionName} from "./schemas/unit_price";
  13. import _ from "lodash";
  14. const scMathUtil = require('../../../public/scMathUtil').getUtil();
  15. class UnitPriceModel extends BaseModel {
  16. /**
  17. * 构造函数
  18. *
  19. * @return {void}
  20. */
  21. constructor() {
  22. let parent = super();
  23. parent.model = UnitPriceSchema;
  24. parent.init();
  25. }
  26. /**
  27. * 根据单价文件id获取单价数据
  28. *
  29. * @param {Number} fileId
  30. * @return {Promise}
  31. */
  32. async getDataByFileId(fileId) {
  33. fileId = parseInt(fileId);
  34. if (isNaN(fileId) || fileId <= 0) {
  35. return null;
  36. }
  37. let unitPriceList = await this.db.model.find({unit_price_file_id: fileId});
  38. if (unitPriceList.length <= 0) {
  39. return null;
  40. }
  41. // 整理数据
  42. let result = {};
  43. for(let tmp of unitPriceList) {
  44. let index = this.getIndex(tmp,['code','name','specs','unit','type'])
  45. result[index] = tmp;
  46. }
  47. return result;
  48. }
  49. /**
  50. * 设置场景
  51. *
  52. * @param {string} scene
  53. * @return {void}
  54. */
  55. setScene(scene = '') {
  56. switch (scene) {
  57. // 新增数据的验证规则
  58. case 'add':
  59. this.model.schema.path('base_price').required(true);
  60. this.model.schema.path('market_price').required(true);
  61. this.model.schema.path('name').required(true);
  62. this.model.schema.path('code').required(true);
  63. // this.model.schema.path('unit').required(true);
  64. this.model.schema.path('type').required(true);
  65. this.model.schema.path('unit_price_file_id').required(true);
  66. }
  67. }
  68. /**
  69. * 新增单价数据
  70. *
  71. * @param {Object} data
  72. * @param {Number} unitPriceFileId
  73. * @param {Number} gljCount
  74. * @return {Promise} 返回数据以及是否新增
  75. */
  76. async addUnitPrice(data, unitPriceFileId, gljCount = 0) {
  77. if (data.original_code===undefined||data.code === undefined || data.project_id === undefined || data.name === undefined
  78. || data.market_price === undefined) {
  79. return [null, false];
  80. }
  81. // 先查找是否有原始code相同的记录
  82. let unitPriceData = await this.findDataByCondition({original_code: data.original_code, unit_price_file_id: unitPriceFileId}, null, false);
  83. // 如果有记录,判断是否存在一样的名称,单位...等,有则直接返回数据
  84. let unitPrice = this.isPropertyInclude(unitPriceData,['name','specs','unit','type'],data);
  85. if(unitPrice){
  86. return [unitPrice, false];
  87. }
  88. // 如果不存在基价单价,则在数据源中获取
  89. if (data.base_price === undefined) {
  90. let firstUnitPrice = unitPriceData[0] !== undefined ? unitPriceData[0] : [];
  91. data.base_price = firstUnitPrice.base_price !== undefined ? firstUnitPrice.base_price : 0;
  92. data.type = firstUnitPrice.type !== undefined ? firstUnitPrice.type : 0;
  93. }
  94. let insertData = {
  95. code: data.code,
  96. base_price: data.base_price,
  97. market_price: data.market_price,
  98. unit_price_file_id: unitPriceFileId,
  99. name: data.name,
  100. specs:data.specs,
  101. original_code:data.original_code,
  102. unit:data.unit,
  103. type: data.type,
  104. short_name: data.shortName !== undefined ? data.shortName : '',
  105. glj_id: data.glj_id
  106. };
  107. // 如果原始编码能找到,但不存在一样的编号,名称,单位.更改 等,更改code和添加新增标记
  108. if (unitPriceData&&unitPriceData.length>0) {
  109. insertData.code = data.original_code+"-"+unitPriceData.length;
  110. insertData.is_add=1;
  111. }
  112. let addPriceResult = await this.add(insertData);
  113. return [addPriceResult, true];
  114. }
  115. /**
  116. * 新增记录
  117. *
  118. * @param {object} data
  119. * @return {Promise}
  120. */
  121. async add(data) {
  122. let counterModel = new CounterModel();
  123. if (data instanceof Array) {
  124. // 如果是批量新增
  125. for(let tmp in data) {
  126. data[tmp].id = await counterModel.getId(collectionName);
  127. }
  128. } else {
  129. data.id = await counterModel.getId(collectionName);
  130. }
  131. this.setScene('add');
  132. return this.db.model.create(data);
  133. }
  134. /**
  135. * 判断数据中是否包含某个市场价格的记录
  136. *
  137. * @param {Array} data
  138. * @param {Number} price
  139. * @return {Number}
  140. */
  141. isPriceIncluded(data, price) {
  142. let index = -1;
  143. if (data.length <= 0) {
  144. return index;
  145. }
  146. for(let tmp in data) {
  147. if (data[tmp].market_price === price) {
  148. index = tmp;
  149. break;
  150. }
  151. }
  152. return index;
  153. }
  154. isPropertyInclude(data,pops,obj){
  155. let condition={};
  156. if (data.length <= 0) {
  157. return null;
  158. }
  159. if(pops instanceof Array){
  160. for(let p of pops){
  161. if(obj[p]){
  162. condition[p]=obj[p]
  163. }
  164. }
  165. }else {
  166. condition[pops]=obj[pops]
  167. }
  168. return _.find(data,condition);
  169. }
  170. /**
  171. * 更新市场单价
  172. *
  173. * @param {Object} condition
  174. * @param {Object} updateData
  175. * @param {String} extend
  176. * @return {Promise}
  177. */
  178. async updatePrice(condition, updateData, extend = '') {
  179. if (Object.keys(condition).length <= 0 || Object.keys(updateData).length <= 0) {
  180. return false;
  181. }
  182. // 首先查找相应的数据判断工料机类型
  183. let unitPriceData = await this.findDataByCondition(condition);
  184. if (!unitPriceData) {
  185. throw '找不到对应的单价数据';
  186. }
  187. /* // 基价单价的计算-----先不考虑同步
  188. switch (unitPriceData.type) {
  189. // 主材、设备自动赋值基价单价=市场单价
  190. case GLJTypeConst.MAIN_MATERIAL:
  191. case GLJTypeConst.EQUIPMENT:
  192. updateData.base_price = updateData.market_price;
  193. break;
  194. }*/
  195. // 额外更新数据
  196. if (extend !== '') {
  197. extend = JSON.parse(extend);
  198. for (let code in extend) {
  199. let extendUpdateData = {
  200. market_price: extend[code].market_price,
  201. };
  202. let tmpCondition = {
  203. unit_price_file_id: unitPriceData.unit_price_file_id,
  204. code: code
  205. };
  206. let extendResult = await this.db.update(tmpCondition, extendUpdateData);
  207. if (!extendResult) {
  208. throw '更新额外数据,编码为' + code + '的数据失败!';
  209. }
  210. }
  211. }
  212. let result = await this.db.update(condition, updateData);
  213. return result.ok !== undefined && result.ok === 1;
  214. }
  215. async updateUnitPrice(data){
  216. //查找并更新单价
  217. let doc={};
  218. doc[data.field]=data.newval;
  219. let unitPrice = await this.db.findAndModify({id:data.id},doc);
  220. if(!unitPrice){
  221. throw "没有找到对应的单价";
  222. }
  223. //查找是否是属于某个项目工料机的组成物
  224. let mixRatioModel = new MixRatioModel();
  225. let condition = {unit_price_file_id:unitPrice.unit_price_file_id, code:unitPrice.code,name: unitPrice.name, specs: unitPrice.specs,unit:unitPrice.unit,type:unitPrice.type};
  226. let mixRatioList = await mixRatioModel.findDataByCondition(condition, null, false);
  227. let connectKeyMap={};
  228. //找到则计算项目工料机组成物的价格并更新
  229. let rList= [];
  230. if(mixRatioList&&mixRatioList.length>0){
  231. for(let m of mixRatioList){
  232. if(!connectKeyMap.hasOwnProperty(m.connect_key)){//为了去重复,组成物会与其它项目同步,所以有可能重复。
  233. rList.push(await this.updateParentUnitPrice(m,data.field));
  234. connectKeyMap[m.connect_key]=true;
  235. }
  236. }
  237. }
  238. return rList;
  239. }
  240. async updateParentUnitPrice(mixRatio,fieid){
  241. //查找该工料机所有组成物
  242. let indexList = ['code','name','specs','unit','type'];
  243. let mixRatioModel = new MixRatioModel();
  244. let mixRatioMap = await mixRatioModel.findDataByCondition({unit_price_file_id:mixRatio.unit_price_file_id,connect_key:mixRatio.connect_key}, null, false,indexList);
  245. //查找对应的价格
  246. let codeList = [];
  247. let nameList = [];
  248. let specsList= [];
  249. let typeList = [];
  250. let unitList = [];
  251. for(let mk in mixRatioMap){
  252. codeList.push(mixRatioMap[mk].code);
  253. nameList.push(mixRatioMap[mk].name);
  254. specsList.push(mixRatioMap[mk].specs);
  255. typeList.push(mixRatioMap[mk].type);
  256. unitList.push(mixRatioMap[mk].unit);
  257. }
  258. let condition = {unit_price_file_id: mixRatio.unit_price_file_id,code: {"$in": codeList}, name: {"$in": nameList},specs:{"$in": specsList},type:{"$in": typeList},unit:{"$in": unitList}};
  259. let priceMap = await this.findDataByCondition(condition, {_id: 0}, false, indexList);
  260. let sumPrice=0;
  261. for(let pk in priceMap){
  262. let price = parseFloat(priceMap[pk][fieid]);
  263. let consumption = parseFloat(mixRatioMap[pk].consumption);
  264. sumPrice +=scMathUtil.roundTo(price*consumption,-6);
  265. }
  266. sumPrice= scMathUtil.roundTo(sumPrice,-6);
  267. if(sumPrice<=0){
  268. return null;
  269. }
  270. //更新父价格
  271. let keyList = mixRatio.connect_key.split("|-|");
  272. let pcondition = {
  273. unit_price_file_id:mixRatio.unit_price_file_id,
  274. code:keyList[0]
  275. };
  276. for(let i = 1;i<keyList.length;i++){
  277. if(keyList[i]!='null'){
  278. pcondition[indexList[i]]=keyList[i];
  279. }
  280. }
  281. let doc={};
  282. doc[fieid]=sumPrice;
  283. let uprice = await this.db.findAndModify(pcondition,doc);
  284. uprice[fieid]=sumPrice;
  285. return uprice;
  286. }
  287. /**
  288. * 复制单价文件数据
  289. *
  290. * @param {Number} currentUnitPriceId
  291. * @param {Number} changeUnitPriceId
  292. * @return {Promise}
  293. */
  294. async copyNotExist(currentUnitPriceId, changeUnitPriceId) {
  295. let result = false;
  296. // 首先查找原单价文件id下的数据
  297. let currentUnitList = await this.findDataByCondition({unit_price_file_id: currentUnitPriceId}, null, false);
  298. if (currentUnitList === null) {
  299. return result;
  300. }
  301. // 过滤mongoose格式
  302. currentUnitList = JSON.stringify(currentUnitList);
  303. currentUnitList = JSON.parse(currentUnitList);
  304. let codeList = [];
  305. for (let tmp of currentUnitList) {
  306. if (codeList.indexOf(tmp.code) >= 0) {
  307. continue;
  308. }
  309. codeList.push(tmp.code);
  310. }
  311. // 查找即将更替的单价文件是否存在对应的工料机数据
  312. let condition = {unit_price_file_id: changeUnitPriceId, code: {"$in": codeList}};
  313. let targetUnitList = await this.findDataByCondition(condition, null, false, 'code');
  314. // 如果没有重叠的数据则原有的数据都复制一份
  315. let insertData = [];
  316. for (let tmp of currentUnitList) {
  317. if (targetUnitList !== null && targetUnitList[tmp.code] !== undefined) {
  318. continue;
  319. }
  320. // 删除原有id信息
  321. delete tmp._id;
  322. delete tmp.id;
  323. tmp.unit_price_file_id = changeUnitPriceId;
  324. insertData.push(tmp);
  325. }
  326. return insertData.length > 0 ? this.add(currentUnitList) : true;
  327. }
  328. }
  329. export default UnitPriceModel;