glj.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /* eslint-disable no-param-reassign */
  2. import {
  3. ConfigMaterialKey,
  4. GljType,
  5. IBaseGlj,
  6. ICalcOption,
  7. IComponent,
  8. IConfigMaterial,
  9. IDecimal,
  10. IInfoPriceItem,
  11. IProjectGlj,
  12. IProperty,
  13. ITenderSetting,
  14. TaxType,
  15. } from '@sc/types';
  16. import { roundForObj } from '@sc/util';
  17. import { find } from 'lodash';
  18. export const getInfoMarketPrice = (info: IInfoPriceItem, taxType: TaxType) => {
  19. // 1: 一般计税 2: 简易计税
  20. const fieldArray = ['noTaxPrice']; // 一般计税 - 不含税价 || 简易计税 - 含税价
  21. if (taxType === TaxType.GENERAL) {
  22. fieldArray.push('taxPrice');
  23. } else {
  24. fieldArray.unshift('taxPrice');
  25. }
  26. // 一个放后面,一个放前面
  27. let infoPrice = (info as any)[fieldArray[0]];
  28. if (infoPrice === null || infoPrice === undefined) infoPrice = (info as any)[fieldArray[1]]; // 信息价只有一个价格(含税价/不含税价),则不分计税方式,套用仅有的价格。
  29. return parseFloat(infoPrice);
  30. };
  31. // 计算采保费率后的市场价
  32. export const calcMarketPriceByInfoPrice = (infoPrice: number, purchaseFeeRate: number, decimal: number) => {
  33. if (!purchaseFeeRate) return infoPrice;
  34. return roundForObj(infoPrice * (1 + purchaseFeeRate / 100), decimal);
  35. };
  36. // roundForObj()
  37. // 返回五大项组成的索引
  38. export const getIndex = (obj: IBaseGlj, props = ['code', 'name', 'specs', 'unit', 'type']): string => {
  39. let index = '';
  40. //! 优化:字符串拼接比数组push、join操作快很多,大项目下影响较大,所以使用字符串拼接
  41. for (let i = 0; i < props.length; i += 1) {
  42. const p = props[i];
  43. const tmpK = obj[p] === undefined || obj[p] === null || obj[p] === '' ? 'null' : obj[p];
  44. const str = i === props.length - 1 ? tmpK : `${tmpK}|-|`;
  45. index += str;
  46. }
  47. return index;
  48. };
  49. // 是否是人工
  50. export const isLabour = (type: GljType) => {
  51. return type === GljType.LABOUR;
  52. };
  53. // 是否是材料
  54. export const isMaterial = (type: GljType) => {
  55. const rootType = +String(type).charAt(0);
  56. return rootType === 2;
  57. };
  58. // 是否是机械
  59. export const isMachine = (type: GljType) => {
  60. const rootType = +String(type).charAt(0);
  61. return rootType === 3;
  62. };
  63. /**
  64. * 判断工料机类型是否有组成物
  65. *
  66. * @param projectGlj 可以不传这个,默认会按glj去取
  67. *
  68. */
  69. export const hasComponent = (projectGlj?: IProjectGlj) => {
  70. // 有组成物的类型
  71. const typeMap: { [key: number]: boolean } = {
  72. 202: true,
  73. 203: true,
  74. 204: true,
  75. 301: true,
  76. 304: true,
  77. 4: true,
  78. };
  79. if (projectGlj) {
  80. return typeMap[projectGlj.type] === true && projectGlj.components && projectGlj.components.length > 0;
  81. }
  82. return false;
  83. };
  84. const getProjectGlj = (glj: IBaseGlj, projectGljMap: Record<string, IBaseGlj>, index?: string) => {
  85. index = index || getIndex(glj);
  86. const projectGlj = projectGljMap[index] as IProjectGlj;
  87. if (projectGlj) return projectGlj;
  88. return undefined;
  89. };
  90. /**
  91. *
  92. * @param fieldID 如"glj.unitPrice"
  93. *
  94. */
  95. export const getDecimal = (fieldID: string, decimal?: any) => {
  96. if (decimal) {
  97. if (fieldID.indexOf('.') !== -1) {
  98. const keyArray = fieldID.split('.');
  99. return decimal[keyArray[0]][keyArray[1]];
  100. }
  101. return decimal[fieldID];
  102. }
  103. return 0;
  104. };
  105. export const getMarketPrice = (
  106. projectGlj: IProjectGlj,
  107. tenderCoe = 1,
  108. projectGljMap: Record<string, IBaseGlj>,
  109. decimalObj: IDecimal
  110. ) => {
  111. if (hasComponent(projectGlj)) {
  112. let parentPrice = 0;
  113. for (const c of projectGlj.components as IComponent[]) {
  114. const cProjectGlj = getProjectGlj(c, projectGljMap);
  115. if (cProjectGlj) {
  116. let cMarketPrice = getMarketPrice(cProjectGlj, 1, projectGljMap, decimalObj);
  117. if (tenderCoe !== 1) cMarketPrice = roundForObj(cMarketPrice * tenderCoe, decimalObj.glj.unitPrice);
  118. const quantity = roundForObj(c.consumption, decimalObj.glj.quantity);
  119. const sumPrice = roundForObj(cMarketPrice * quantity, decimalObj.process);
  120. parentPrice = roundForObj(parentPrice + sumPrice, decimalObj.process);
  121. }
  122. }
  123. return roundForObj(parentPrice, decimalObj.glj.unitPriceHasMix);
  124. }
  125. const marketPrice = roundForObj(projectGlj.marketPrice, decimalObj.glj.unitPrice);
  126. // 调价的时候还要乘以调价系数
  127. if (tenderCoe !== 1) return roundForObj(marketPrice * tenderCoe, decimalObj.glj.unitPrice);
  128. return marketPrice;
  129. };
  130. // 取工料机基价(定额价)
  131. export const getBasePrice = (projectGlj: IProjectGlj, decimalObj: IDecimal) => {
  132. let decimalKey = 'glj.unitPrice';
  133. if (hasComponent(projectGlj)) decimalKey = 'glj.unitPriceHasMix';
  134. const decimal = getDecimal(decimalKey, decimalObj);
  135. return roundForObj(projectGlj.basePrice, decimal);
  136. };
  137. export const getTenderPriceCoe = (projectGlj: IProjectGlj, tenderSetting?: ITenderSetting) => {
  138. let coe = 1;
  139. if (projectGlj.noAdjustPrice === false && tenderSetting) {
  140. coe = tenderSetting.gljPriceTenderCoe ? tenderSetting.gljPriceTenderCoe : 1;
  141. }
  142. return coe;
  143. };
  144. // 判断是否暂估
  145. export const isEvaluate = (projectGljID: string, configMaterials: IConfigMaterial) => {
  146. const materials = configMaterials[ConfigMaterialKey.EVALUATE];
  147. return !!find(materials, { isRelated: true, projectGljID });
  148. };
  149. // 判断是否计算价差
  150. export const calcPriceDiff = (projectGlj: IProjectGlj, configMaterials: IConfigMaterial, calcOption?: ICalcOption) => {
  151. if (calcOption) {
  152. const { calcEst, calcMain, calcAdd } = calcOption;
  153. if (isEvaluate(projectGlj.ID, configMaterials)) return calcEst; // 先按是否暂估判断
  154. // 再判断是否是主材和设备
  155. if (projectGlj.type === GljType.MAIN_MATERIAL || projectGlj.type === GljType.EQUIPMENT) return calcMain;
  156. // 再判断是否新增
  157. if (projectGlj.isAdd) return calcAdd;
  158. }
  159. return true;
  160. };
  161. // 取工料机的价格在确定subject数据已经获取全的情况下使用
  162. export const getPrice = (
  163. glj: IBaseGlj,
  164. projectGljMap: Record<string, IBaseGlj>,
  165. unitProperty: { tenderSetting?: ITenderSetting },
  166. constructionProperty: { decimal: IDecimal; calcOption?: ICalcOption },
  167. configMaterial: IConfigMaterial,
  168. tender?: boolean
  169. ) => {
  170. let marketPrice = 0;
  171. let basePrice = 0;
  172. let tenderPrice = 0; // 调后价
  173. let adjustPrice = 0; // 调整价
  174. const projectGlj = getProjectGlj(glj, projectGljMap);
  175. if (projectGlj) {
  176. marketPrice = getMarketPrice(projectGlj, 1, projectGljMap, constructionProperty.decimal);
  177. tenderPrice = marketPrice;
  178. if (tender === true) {
  179. const tenderCoe = getTenderPriceCoe(projectGlj, unitProperty.tenderSetting);
  180. tenderPrice = getMarketPrice(projectGlj, tenderCoe, projectGljMap, constructionProperty.decimal);
  181. }
  182. if (calcPriceDiff(projectGlj, configMaterial, constructionProperty.calcOption)) {
  183. // 计取价差
  184. basePrice = getBasePrice(projectGlj, constructionProperty.decimal);
  185. } else {
  186. // 不计价差时 基价也为市场价
  187. basePrice = marketPrice;
  188. }
  189. adjustPrice = basePrice;
  190. }
  191. return { marketPrice, basePrice, tenderPrice, adjustPrice, projectGlj };
  192. };