|
|
@@ -10,27 +10,42 @@ INTERFACE_EXPORT = (() => {
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
- * @param {String} userID - 用户ID
|
|
|
* @param {String} areaKey - 地区标识,如:'安徽@马鞍山',有些地区的接口只是取值上有不同,共有一个接口脚本, 需要通过地区标识确定一些特殊处理
|
|
|
* @param {Number} exportKind - 导出类型,招标、投标、控制价
|
|
|
* @param {Object} projectData - 项目表数据:{ 建设项目Data, children: [单位工程...] }
|
|
|
* @param {Object} tenderDetailMap - 单位工程ID与getData接口数据(projectObj.project的结构)的映射。
|
|
|
* @return {Promise<Array>} - 返回的数据结构必须按照规定:[{ data, exportKind, fileName }],参考web\building_saas\standard_interface\index.js中的注释说明
|
|
|
*/
|
|
|
- async function entry(userID, areaKey, exportKind, projectData, tenderDetailMap) {
|
|
|
+ async function entry(areaKey, exportKind, projectData, tenderDetailMap) {
|
|
|
const {
|
|
|
- CONFIG: { TYPE, EXPORT_KIND },
|
|
|
+ CONFIG: { TYPE },
|
|
|
UTIL: {
|
|
|
getValueByKey,
|
|
|
+ getHan,
|
|
|
+ getFee,
|
|
|
},
|
|
|
Element,
|
|
|
- } = XML_EXPORT_BASE;
|
|
|
+ } = INTERFACE_EXPORT_BASE;
|
|
|
+
|
|
|
+ const {
|
|
|
+ EXPORT_KIND: { BID_INVITATION, BID_SUBMISSION, CONTROL },
|
|
|
+ fixedFlag,
|
|
|
+ } = window.commonConstants
|
|
|
+
|
|
|
+ const { isEmptyVal, isDef } = window.commonUtil;
|
|
|
|
|
|
const czzt = {
|
|
|
- [EXPORT_KIND.BID_INVITATION]: '招标',
|
|
|
- [EXPORT_KIND.BID_SUBMISSION]: '投标',
|
|
|
- [EXPORT_KIND.CONTROL]: '招标控制',
|
|
|
+ [BID_INVITATION]: '招标',
|
|
|
+ [BID_SUBMISSION]: '投标',
|
|
|
+ [CONTROL]: '招标控制',
|
|
|
};
|
|
|
+
|
|
|
+ const isBidInvitation = exportKind === BID_INVITATION; // 是否是招标
|
|
|
+ const isBidSubmission = exportKind === BID_SUBMISSION; // 是否是投标
|
|
|
+ const isControl = exportKind === CONTROL; // 是否是控制价
|
|
|
+
|
|
|
+ // 节点定义--------------------------------
|
|
|
+
|
|
|
// 建设项目基本信息
|
|
|
function JingJiBiao(projectName, information) {
|
|
|
const attrs = [
|
|
|
@@ -46,6 +61,9 @@ INTERFACE_EXPORT = (() => {
|
|
|
];
|
|
|
Element.call(this, 'JingJiBiao', attrs);
|
|
|
}
|
|
|
+
|
|
|
+ const subArea = areaKey.split('@')[1];
|
|
|
+
|
|
|
// 招标信息
|
|
|
function ZhaoBiaoXx(information) {
|
|
|
const attrs = [
|
|
|
@@ -58,10 +76,23 @@ INTERFACE_EXPORT = (() => {
|
|
|
{ name: 'BzTime', value: getValueByKey(information, ''), type: TYPE.DATE }, // 编制时间
|
|
|
{ name: 'FhTime', value: getValueByKey(information, ''), type: TYPE.DATE }, // 复核时间
|
|
|
];
|
|
|
+ // 额外字段
|
|
|
+ const extraMap = {
|
|
|
+ '淮北': [
|
|
|
+ { name: 'ZbrNssbh', value: getValueByKey(information, '') }, // 招标人纳税识别号
|
|
|
+ { name: 'ZxrNssbh', value: getValueByKey(information, '') }, // 造价咨询人纳税识别号
|
|
|
+ { name: 'ZbrDbSfzh', value: getValueByKey(information, '') }, // 招标人法定代表人或其授权人身份证号
|
|
|
+ { name: 'ZxrNssbh', value: getValueByKey(information, '') }, // 造价咨询人法定代表或其授权人纳税识别号
|
|
|
+ ]
|
|
|
+ };
|
|
|
+ if (extraMap[subArea]) {
|
|
|
+ attrs.push(...extraMap[subArea]);
|
|
|
+ }
|
|
|
Element.call(this, 'ZhaoBiaoXx', attrs);
|
|
|
}
|
|
|
- // 招标信息
|
|
|
- function ZhaoBiaoXx(information) {
|
|
|
+
|
|
|
+ // 招标控制价信息
|
|
|
+ function ZhaoBiaoKzXx(information) {
|
|
|
const attrs = [
|
|
|
{ name: 'Zbr', value: getValueByKey(information, '') }, // 招标人
|
|
|
{ name: 'Zxr', value: getValueByKey(information, '') }, // 造价咨询人
|
|
|
@@ -71,13 +102,280 @@ INTERFACE_EXPORT = (() => {
|
|
|
{ name: 'Fhr', value: getValueByKey(information, '') }, // 复核人
|
|
|
{ name: 'BzTime', value: getValueByKey(information, ''), type: TYPE.DATE }, // 编制时间
|
|
|
{ name: 'FhTime', value: getValueByKey(information, ''), type: TYPE.DATE }, // 复核时间
|
|
|
+ { name: 'Zbkzj', value: getValueByKey(information, ''), type: TYPE.DECIMAL }, // 控制价总价(元),取“投标报价”的金额。
|
|
|
];
|
|
|
- Element.call(this, 'ZhaoBiaoXx', attrs);
|
|
|
+ // 额外字段
|
|
|
+ const extraMap = {
|
|
|
+ '淮北': [
|
|
|
+ { name: 'ZbrNssbh', value: getValueByKey(information, '') }, // 招标人纳税识别号
|
|
|
+ { name: 'ZxrNssbh', value: getValueByKey(information, '') }, // 造价咨询人纳税识别号
|
|
|
+ { name: 'ZbrDbSfzh', value: getValueByKey(information, '') }, // 招标人法定代表人或其授权人身份证号
|
|
|
+ { name: 'ZxrNssbh', value: getValueByKey(information, '') }, // 造价咨询人法定代表或其授权人纳税识别号
|
|
|
+ ]
|
|
|
+ };
|
|
|
+ if (extraMap[subArea]) {
|
|
|
+ attrs.push(...extraMap[subArea]);
|
|
|
+ }
|
|
|
+ Element.call(this, 'ZhaoBiaoKzXx', attrs);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 招标控制价信息
|
|
|
+ function TouBiaoXx(information) {
|
|
|
+ const attrs = [
|
|
|
+ { name: 'Zbr', value: getValueByKey(information, '') }, // 招标人
|
|
|
+ { name: 'Tbr', value: getValueByKey(information, '') }, // 投标人
|
|
|
+ { name: 'TbrDb', value: getValueByKey(information, '') }, // 投标人法定代表或其授权
|
|
|
+ { name: 'Bzr', value: getValueByKey(information, '') }, // 编制人
|
|
|
+ { name: 'BzTime', value: getValueByKey(information, ''), type: TYPE.DATE }, // 编制时间
|
|
|
+ { name: 'Tbzj', value: getValueByKey(information, ''), type: TYPE.DECIMAL }, // 控制价总价(元),取“投标报价”的金额。
|
|
|
+ ];
|
|
|
+ // 额外字段
|
|
|
+ const extraMap = {
|
|
|
+ '淮北': [
|
|
|
+ { name: 'ZbrNssbh', value: getValueByKey(information, '') }, // 招标人纳税识别号
|
|
|
+ { name: 'TbrNssbh', value: getValueByKey(information, '') }, // 投标人纳税识别号
|
|
|
+ { name: 'TbrDbsfzh', value: getValueByKey(information, '') }, // 投标人法定代表或其授权人身份证号
|
|
|
+ ]
|
|
|
+ };
|
|
|
+ if (extraMap[subArea]) {
|
|
|
+ attrs.push(...extraMap[subArea]);
|
|
|
+ }
|
|
|
+ Element.call(this, 'TouBiaoXx', attrs);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 单项工程信息,因项目管理中无“单项工程”这一层,从单位工程的工程特征信息中拼凑出来
|
|
|
+ function Dxgcxx(code, name) {
|
|
|
+ const attrs = [
|
|
|
+ { name: 'Dxgcbh', value: code }, // 单项工程编号
|
|
|
+ { name: 'Dxgcmc', value: name }, // 单项工程名称
|
|
|
+ ];
|
|
|
+ Element.call(this, 'Dxgcxx', attrs);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 单位工程信息
|
|
|
+ function Dwgcxx(tenderName, feature) {
|
|
|
+ const attrs = [
|
|
|
+ { name: 'Dwgcbh', value: getValueByKey(feature, '') }, // 单位工程编号
|
|
|
+ { name: 'Dwgcmc', value: tenderName }, // 单位工程名称
|
|
|
+ ];
|
|
|
+ Element.call(this, 'Dwgcxx', attrs);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 取费信息(费率信息)
|
|
|
+ function Qfxx() {
|
|
|
+ Element.call(this, 'Qfxx');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计价费率表
|
|
|
+ function JjFlb() {
|
|
|
+ Element.call(this, 'JjFlb');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 费率明细名称-编码映射表
|
|
|
+ const FeeRateCodeMap = {
|
|
|
+ 冬季施工增加费: 'DJF',
|
|
|
+ 雨季施工增加费: 'YJF',
|
|
|
+ 夜间施工增加费: 'YEF',
|
|
|
+ 工地转移费: 'ZYF',
|
|
|
+ 高原施工增加费: 'GYF',
|
|
|
+ 风沙地区增加费: 'FSF',
|
|
|
+ 沿海地区增加费: 'YHF',
|
|
|
+ 行车干扰增加费: 'XCF',
|
|
|
+ 施工辅助费: 'SFF',
|
|
|
+ 养老保险费: 'YLF',
|
|
|
+ 失业保险费: 'SYF',
|
|
|
+ 医疗保险费: 'YBF',
|
|
|
+ 住房公积金: 'ZFF',
|
|
|
+ 工伤保险费: 'GSF',
|
|
|
+ 基本费用: 'JBF',
|
|
|
+ 主副食运费补贴: 'YFF',
|
|
|
+ 职工探亲补贴: 'TQF',
|
|
|
+ 职工取暖补贴: 'QNF',
|
|
|
+ 财务费用: 'CWF',
|
|
|
+ 利润: 'LR',
|
|
|
+ 税金: 'SJ',
|
|
|
+ };
|
|
|
+ // 费率工程名称-取费类别映射表
|
|
|
+ const FeeRateTypeMap = {
|
|
|
+ 土方: 1,
|
|
|
+ 石方: 3,
|
|
|
+ 运输: 2,
|
|
|
+ 路面: 4,
|
|
|
+ 隧道: 11,
|
|
|
+ 构造物I: 5,
|
|
|
+ '构造物I(不计冬)': 16,
|
|
|
+ 构造物II: 6,
|
|
|
+ '构造物III(桥梁)': 9,
|
|
|
+ '构造物III(除桥以外不计雨)': 8,
|
|
|
+ 技术复杂大桥: 10,
|
|
|
+ '钢材及钢结构(桥梁)': 12,
|
|
|
+ '钢材及钢结构(除桥以外不计夜)': 13,
|
|
|
+ '费率为0': 17,
|
|
|
+ '路面(不计雨)': 4,
|
|
|
+ '构造物I(不计雨)': 16,
|
|
|
+ '构造物III(除桥以外)': 8,
|
|
|
+ '钢材及钢结构(除桥以外)': 13,
|
|
|
+ 设备: 15,
|
|
|
+ 量价: 14,
|
|
|
+
|
|
|
+ };
|
|
|
+ // 计价费率表明细,造价书费率页面左侧最底层数据
|
|
|
+ function JjFlbMx(rootItem, item) {
|
|
|
+ const rate = isEmptyVal(item.rate) ? '100' : item.rate; // 为空时输出=100,为0时输出=0
|
|
|
+ const attrs = [
|
|
|
+ { name: 'Bm', value: FeeRateCodeMap[item.name] }, // 编码
|
|
|
+ { name: 'Name', value: item.name }, // 名称
|
|
|
+ { name: 'Fl', value: rate, type: TYPE.DECIMAL }, // 费率
|
|
|
+ { name: 'Qflb', value: FeeRateTypeMap[rootItem.name], type: TYPE.INT }, // 取费类别
|
|
|
+ ];
|
|
|
+ Element.call(this, 'JjFlbMx', attrs);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计价费率项
|
|
|
+ function JjFlx() {
|
|
|
+ Element.call(this, 'JjFlx');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计价费率项明细,造价书费率页面右侧最顶层数据
|
|
|
+ function JjFlxMx(item) {
|
|
|
+ // 编码取名称拼音首字母
|
|
|
+ const allHanName = getHan(item.name || '');
|
|
|
+ const code = pinyinUtil.getFirstLetter(allHanName).toLowerCase();
|
|
|
+ let value;
|
|
|
+ if (isDef(item.value)) {
|
|
|
+ value = item.value;
|
|
|
+ } else {
|
|
|
+ const selected = item.optionList.find(item => item.selected);
|
|
|
+ value = selected.name;
|
|
|
+ }
|
|
|
+ const attrs = [
|
|
|
+ { name: 'Bm', value: code }, // 编码
|
|
|
+ { name: 'Mc', value: item.name }, // 名称
|
|
|
+ { name: 'ShuZhi', value: value }, // 数值
|
|
|
+ ];
|
|
|
+ Element.call(this, 'JjFlxMx', attrs);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清单项目
|
|
|
+ function QdXm() {
|
|
|
+ Element.call(this, 'QdXm');
|
|
|
+ }
|
|
|
+ // 标题类别:1=100~700清单合计,2=暂估价合计,3=清单不包含暂估价合计,4=计日工,5=暂列金额(不含计日工总额)),6=投标报价,0=其他
|
|
|
+ const BillsTitleType = {
|
|
|
+ [fixedFlag.ONE_SEVEN_BILLS]: '1',
|
|
|
+ [fixedFlag.PROVISIONAL_TOTAL]: '2',
|
|
|
+ [fixedFlag.BILLS_TOTAL_WT_PROV]: '3',
|
|
|
+ [fixedFlag.DAYWORK_LABOR]: '4',
|
|
|
+ [fixedFlag.PROVISIONAL]: '5',
|
|
|
+ [fixedFlag.TOTAL_COST]: '6',
|
|
|
+ };
|
|
|
+ // 清单标题 造价书的第一层数据。
|
|
|
+ function QdBt(node) {
|
|
|
+ const row = node.row();
|
|
|
+ const fee = isBidInvitation ? '0' : getFee(node.data.fees, 'common.tenderTotalFee')
|
|
|
+ const attrs = [
|
|
|
+ { name: 'Xh', value: row, type: TYPE.INT }, // 序号
|
|
|
+ { name: 'Bm', value: node.data.code }, // 编码
|
|
|
+ { name: 'Name', value: node.data.name }, // 名称
|
|
|
+ { name: 'Je', value: fee, type: TYPE.DECIMAL }, // 金额
|
|
|
+ { name: 'Code', value: `F${row}` }, // 行引用
|
|
|
+ { name: 'Jsgs', value: node.data.calcBase }, // 计算基数
|
|
|
+ { name: 'Lb', value: BillsTitleType[node.getFlag()], type: TYPE.INT }, // 类别
|
|
|
+ ];
|
|
|
+ Element.call(this, 'QdBt', attrs);
|
|
|
}
|
|
|
|
|
|
+ // 清单明细 (只有100-700章清单标题输出)
|
|
|
+ function QdMx(node) {
|
|
|
+ const row = node.row();
|
|
|
+ const attrs = [
|
|
|
+ { name: 'Xh', value: row, type: TYPE.INT }, // 序号
|
|
|
+ { name: 'Qdbm', value: node.data.code }, // 编码
|
|
|
+ { name: 'Name', value: node.data.name }, // 名称
|
|
|
+ { name: 'Dw', value: node.data.unit }, // 单位
|
|
|
+ { name: 'Sl', value: node.data.quantity, type: TYPE.DECIMAL }, // 工程量
|
|
|
+ { name: 'Sl2', value: '0', type: TYPE.DECIMAL }, // 工程量2
|
|
|
+ { name: 'Rgf', value: isBidInvitation ? '0' : getFee(node.data.fees, 'labour.tenderTotalFee'), type: TYPE.DECIMAL }, // 人工费
|
|
|
+ ];
|
|
|
+ Element.call(this, 'QdMx', attrs);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 组装数据 --------------------------------------
|
|
|
+
|
|
|
+ // 组装费率数据
|
|
|
+ function setupFeeRate(feeRateDetail) {
|
|
|
+ const qfxx = new Qfxx();
|
|
|
+ const jjflb = new JjFlb();
|
|
|
+ // 费率界面左侧底层数据
|
|
|
+ let curRootItem;
|
|
|
+ feeRateDetail.datas.rates.forEach(item => {
|
|
|
+ if (!item.ParentID) {
|
|
|
+ curRootItem = item;
|
|
|
+ } else if (!item.sum) { // 最底层
|
|
|
+ jjflb.children.push(new JjFlbMx(curRootItem, item));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ // 费率界面右侧顶层数据
|
|
|
+ const jjflx = new JjFlx();
|
|
|
+ const flxmxData = feeRateDetail
|
|
|
+ .getAllSubRates()
|
|
|
+ .filter(item => !item.isSub)
|
|
|
+ .map(item => new JjFlxMx(item));
|
|
|
+ jjflx.children.push(...flxmxData);
|
|
|
+
|
|
|
+ qfxx.children.push(jjflb, jjflx);
|
|
|
+ return qfxx;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 组装清单数据
|
|
|
+ function setupBills(mainTree) {
|
|
|
+ const qdxm = new QdXm();
|
|
|
+ const qdbtData = mainTree.roots.map(node => new QdBt(node));
|
|
|
+ qdxm.children.push(...qdbtData);
|
|
|
+ return qdxm;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 组装单位工程数据
|
|
|
+ function setupTender(tenderData, feature) {
|
|
|
+ const detail = tenderDetailMap[tenderData.ID];
|
|
|
+ const dwgcxx = new Dwgcxx(tenderData.name, feature);
|
|
|
+ dwgcxx.children.push(
|
|
|
+ setupFeeRate(detail.FeeRate),
|
|
|
+ setupBills(detail.mainTree)
|
|
|
+ );
|
|
|
+ return dwgcxx;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 组装建设项目数据
|
|
|
+ function setupConstruction(constructionData) {
|
|
|
+ const information = constructionData.property && constructionData.property.basicInformation || [];
|
|
|
+ const jingJiBiao = new JingJiBiao(constructionData.name, information);
|
|
|
+ // 将单位工程工程特征中,单项工程编号、名称相同的,插入到建设项目和分段(单位工程)的中间层。
|
|
|
+ const midLayerMap = {}; // 单项工程key(code@name)与单项工程节点映射
|
|
|
+ for (const tenderData of constructionData.children) {
|
|
|
+ const feature = tenderData.property && tenderData.property.projectFeature || [];
|
|
|
+ const midLayerCode = getValueByKey(feature, 'singleProjNo');
|
|
|
+ const midLayerName = getValueByKey(feature, 'singleProjName');
|
|
|
+ const midLayerKey = `${midLayerCode}@${midLayerName}`;
|
|
|
+ if (!midLayerMap[midLayerKey]) {
|
|
|
+ jingJiBiao.children.push(midLayerMap[midLayerKey] = new Dxgcxx(midLayerCode, midLayerName));
|
|
|
+ }
|
|
|
+ midLayerMap[midLayerKey].children.push(setupTender(tenderData, feature));
|
|
|
+ }
|
|
|
+ const suffix = INTERFACE_CONFIG[areaKey]['fileSuffix'][exportKind];
|
|
|
+ return [{
|
|
|
+ data: jingJiBiao,
|
|
|
+ exportKind,
|
|
|
+ fileName: `${constructionData.name}${suffix}`
|
|
|
+ }];
|
|
|
+ }
|
|
|
+
|
|
|
+ return setupConstruction(projectData);
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
return {
|
|
|
entry,
|
|
|
};
|
|
|
-})();
|
|
|
+})();
|