Jelajahi Sumber

导入广东接口代码更新

vian 5 tahun lalu
induk
melakukan
42433ece92

File diff ditekan karena terlalu besar
+ 1 - 1
config/config.js


+ 29 - 0
public/common_constants.js

@@ -103,10 +103,39 @@ const commonConstants = (() => {
         Engineering: 'Engineering',
         Tender: 'Tender'
     };
+    // 计税方式
+    const TaxType = {
+        NORMAL: 1,
+        SIMPLE: 2
+    };
+    // 供货方式
+    const supplyType = {
+        //自行采购
+        ZXCG: 0,
+        //部分甲供
+        BFJG: 1,
+        //完全甲供
+        WQJG: 2,
+        //甲定乙供
+        JDYG: 3
+    };
+    const supplyText = {
+        //自行采购
+        ZXCG: '自行采购',
+        //部分甲供
+        BFJG: '部分甲供',
+        //完全甲供
+        WQJG: '完全甲供',
+        //甲定乙供
+        JDYG: '甲定乙供'
+    };
     return {
         fixedFlag,
         billType,
         rationType,
         projectType,
+        TaxType,
+        supplyType,
+        supplyText,
     }
 })();

+ 20 - 2
web/building_saas/main/js/models/importStdInterfaceBase.js

@@ -1,7 +1,5 @@
 'use strict';
 
-const e = require("express");
-
 /**
  *
  *
@@ -158,6 +156,25 @@ const importXMLBase = (() => {
             return obj;
         });
     }
+
+    // 递归获取相关数据,与上方的方法不同的点在:同层可能出现不同节点,上方方法暂时不取消(防止bug)
+    // fields内字段的顺序即决定了提取数据类型的顺序,如fields = [['gruop'], ['item']],则提取的数据同层中group数据在item数据之前
+    function extractItemsRecur(src, fields, extractFuc) {
+        const rst = [];
+        for (const field of fields) {
+            const itemsSrc = arrayValue(src, field);
+            if (itemsSrc.length) {
+                const items = itemsSrc.map(itemSrc => {
+                    const obj = extractFuc(itemSrc, curField);
+                    obj.items = getItemsRecur(itemSrc, fields, extractFuc);
+                    return obj;
+                });
+                rst.push(...items);
+            }
+        }
+        return rst;
+    }
+
     /*
     * 转换计算基数
     * 1.有子项数据,则清空基数
@@ -241,6 +258,7 @@ const importXMLBase = (() => {
         getFlag,
         getBool,
         getItemsRecur,
+        extractItemsRecur,
         readAsTextSync,
     });
 

+ 2 - 21
web/building_saas/main/js/models/main_consts.js

@@ -156,27 +156,8 @@ const zanguCalcType = {
 };
 
 //供货方式
-const supplyType = {
-    //自行采购
-    ZXCG: 0,
-    //部分甲供
-    BFJG: 1,
-    //完全甲供
-    WQJG: 2,
-    //甲定乙供
-    JDYG: 3
-};
-
-const supplyText = {
-    //自行采购
-    ZXCG: '自行采购',
-    //部分甲供
-    BFJG: '部分甲供',
-    //完全甲供
-    WQJG: '完全甲供',
-    //甲定乙供
-    JDYG: '甲定乙供'
-};
+const supplyType = commonConstants.supplyType;
+const supplyText = commonConstants.supplyText;
 
 //三材类别
 const materialType = {

+ 3 - 4
web/over_write/js/guangdong_2018_export.js

@@ -251,10 +251,9 @@ const XMLStandard = (function () {
     };
     // 供料方式
     const Provider = {
-        [supplyType.ZXCG]: '1',
-        [supplyType.BFJG]: '2',
-        [supplyType.WQJG]: '2',
-        [supplyType.WQJG]: '3',
+        [commonConstants.supplyType.ZXCG]: '1',
+        [commonConstants.supplyType.BFJG]: '2',
+        [commonConstants.supplyType.WQJG]: '3',
     }
 
     // 通用设置和工具

+ 240 - 44
web/over_write/js/guangdong_2018_import.js

@@ -8,7 +8,8 @@ const importXML = (() => {
         fixedFlag,
         billType,
         rationType,
-        projectType
+        projectType,
+        TaxType,
     } = commonConstants;
     const { AdjustType } = config;
     const {
@@ -19,6 +20,7 @@ const importXML = (() => {
         getFlag,
         getBool,
         getItemsRecur,
+        extractItemsRecur,
     } = util;
 
     //导入的文件类型,界面选的文件类型是生成项目的文件类型,这里的文件类型指的是,要导入文件的类型,
@@ -156,7 +158,10 @@ const importXML = (() => {
                 engineering: getValue(src, ['_ProjectType']),
                 projectFeature: extractProjectFeature(src),
                 workSummary: extractWorkSummary(src),
-                fbfx: extractFBFX
+                fbfx: extractFBFX,
+                csxm: extractCSXM,
+                other: extractOther,
+                tax: extractTax,
             };
         });
     }
@@ -212,7 +217,7 @@ const importXML = (() => {
         const fees = getFeesFromBasicCost(fbfxSrc); // 分部分项的汇总价
         const items = getItemsRecur(fbfxSrc, fields, (itemSrc, curField) => {
             if (curField[0] === fields[0][0]) { // 分部
-                return extractDivisionalWorks(itemSrc);
+                return extractDivisionalWorks(itemSrc, billType.FB);
             } else {
                 return extractWorkElement(itemSrc, billType.FX);
             }
@@ -223,10 +228,10 @@ const importXML = (() => {
         };
     }
     // 提取分部
-    function extractDivisionalWorks(divisionalSrc) {
+    function extractDivisionalWorks(divisionalSrc, type) {
         // 分部不需要基数,因此不用把基数导入
         const item = {
-            type: billType.FB,
+            type,
             code: getValue(divisionalSrc, ['_Number']),
             name: getValue(divisionalSrc, ['_Name']),
             unit: getValue(divisionalSrc, ['_Unit']),
@@ -243,7 +248,6 @@ const importXML = (() => {
     }
     // 提取分项清单数据(包含定额、定额人材机)
     function extractWorkElement(workElementSrc, type) {
-        // 分项不需要基数,因此不用把基数导入
         const itemCharacterText = getItemCharacterText(getValue(workElementSrc, ['_Attr']));
         const bills = {
             type: type, // 清单类型
@@ -255,6 +259,8 @@ const importXML = (() => {
             jobContent: getJobContent(workElementSrc),
             unit: getValue(workElementSrc, ['_Unit']),
             quantity: getValue(workElementSrc, ['_Quantity']),
+            calcBase: getValue(workElementSrc, ['_QtyFormula']),
+            feeRate: getValue(workElementSrc, ['_Rate']),
             mainBills: getBool(getValue(workElementSrc, ['_Major'])),
             feeCode: getValue(workElementSrc, ['_Code']),
             remark: getValue(workElementSrc, ['_Remark']),
@@ -278,45 +284,44 @@ const importXML = (() => {
                 bills.rations = extractRations(workElementSrc);
             }
         }
-    }
-    // 获取项目特征文本
-    function getItemCharacterText(attr) {
-        const matchStrs = ['
', ';'];
-        const matchStr = matchStrs.find(str => attr.includes(str));
-        return attr.replace(new RegExp(matchStr, 'g'), '\n');
-    }
-    // 获取清单项目特征窗口数据
-    function getItemCharacter(itemText) {
-        const itemsList = itemText.split('\n');
-        const reg = /\d+\.([^:]+)[::](.*)?/;
-        const itemCharacter = [];
-        let idx = 1;
-        itemsList.forEach(str => {
-            str = str.replace(/\s/g, '');
-            const result = reg.exec(str);
-            if (!result) {
-                return;
-            }
-            const name = result[1];
-            const value = result[2] || '';
-            const eigenvalue = value ? [{ value, isSelected: true }] : [];
-            itemCharacter.push({
-                character: name,
-                isChecked: true,
-                serialNo: idx++,
-                eigenvalue
+        // 获取项目特征文本
+        function getItemCharacterText(attr) {
+            const matchStrs = ['
', ';'];
+            const matchStr = matchStrs.find(str => attr.includes(str));
+            return attr.replace(new RegExp(matchStr, 'g'), '\n');
+        }
+        // 获取清单项目特征窗口数据
+        function getItemCharacter(itemText) {
+            const itemsList = itemText.split('\n');
+            const reg = /\d+\.([^:]+)[::](.*)?/;
+            const itemCharacter = [];
+            let idx = 1;
+            itemsList.forEach(str => {
+                str = str.replace(/\s/g, '');
+                const result = reg.exec(str);
+                if (!result) {
+                    return;
+                }
+                const name = result[1];
+                const value = result[2] || '';
+                const eigenvalue = value ? [{ value, isSelected: true }] : [];
+                itemCharacter.push({
+                    character: name,
+                    isChecked: true,
+                    serialNo: idx++,
+                    eigenvalue
+                });
             });
-        });
-        return itemCharacter;
-    }
-    // 获取清单工作内容窗口数据
-    function getJobContent(workElementSrc) {
-        return arrayValue(workElementSrc, ['WorkContent']).map((workContent, idx) => ({
-            content: getValue(workContent, ['_Name']),
-            serialNo: idx + 1,
-            isChecked: true
-        }));
-
+            return itemCharacter;
+        }
+        // 获取清单工作内容窗口数据
+        function getJobContent(workElementSrc) {
+            return arrayValue(workElementSrc, ['WorkContent']).map((workContent, idx) => ({
+                content: getValue(workContent, ['_Name']),
+                serialNo: idx + 1,
+                isChecked: true
+            }));
+        }
     }
     // 提取定额
     function extractRations(workElementSrc) {
@@ -403,9 +408,200 @@ const importXML = (() => {
             const fees = [{ fieldName: 'common', unitFee: getValue(rationSrc, ['_Price']), totalFee: getValue(rationSrc, ['_Total']) }]
             const feesFromCalcItem = getFeesFromCalculationOfItem(rationSrc);
             ration.fees = mergeFees(fees, feesFromCalcItem);
+            ration.rationGLJs = extractRationGLJs(rationSrc);
         }
     }
+    // 提取措施项目
+    function extractCSXM(tenderSrc) {
+        const csxmSrc = getValue(tenderSrc, ['Preliminaries']);
+        const fields = [['DivisionalWorks'], ['WorkElement']];
+        const fees = getFeesFromBasicCost(csxmSrc); // 措施项目的汇总价
+        const items = getItemsRecur(csxmSrc, fields, (itemSrc, curField) => {
+            if (curField[0] === fields[0][0]) {
+                return extractDivisionalWorks(itemSrc, billType.BILL);
+            } else {
+                return extractWorkElement(itemSrc, billType.BILL);
+            }
+        });
+        return {
+            fees,
+            items
+        };
+    }
+    // 提取其他项目
+    function extractOther(tenderSrc) {
+        const sundry = getValue(tenderSrc, ['Sundry']);
+        // SundryCosts 其他项目 ,对于我们软件是其他项目下完整数据,但是广联达的并不是,因此需要Sundry的其他节点来补充这份数据
+        const sundryCosts = getValue(sundry, ['SundryCosts']);
+        // 其他项目汇总费用
+        const sundryFees = [{ fieldName: 'common', totalFee: getValue(sundryCosts, ['_Total']) }];
+        return {
+            fees: sundryFees,
+            sundryCosts: extractData(sundry, 'SundryCosts', [['SundryCostsGroup'], ['SundryCostsItem']]),
+            provisional: extractData(sundry, 'ProvisionalSums', [['ProvisionalSumsGroup'], ['ProvisionalSumsItem']]),
+            specialty: extractData(sundry, 'SpecialtyProvisionalPrice', [['SpecialtyProvisionalPriceGroup'], ['SpecialtyProvisionalPriceItem']],
+                { engineeringContent: getValue(itemSrc, ['_Content']) }, { engineeringContent: getValue(itemSrc, ['_Content']) }),
+            dayWork: extractData(sundry, 'DayWorkRate', [['DayWorkRateGroup'], ['DayWorkRateItem']]),
+            mainContractor: extractData(sundry, 'MainContractorAttendance', [['MainContractorAttendanceGroup'], ['MainContractorAttendanceItem']], { serviceContent: getValue(itemSrc, ['_Content']) }),
+            claim: extractData(sundry, 'ClaimsCost', [['ClaimsCostGroup'], ['ClaimsCostItem']]),
+            visa: extractData(sundry, 'SiteInstructionCost', [['SiteInstructionCostGroup'], ['SiteInstructionCostItem']]),
+        };
+        // 提取标题和明细
+        function extractGroupOrItem(src, isGroup = true, extendAttrs = null) {
+            const source = isGroup
+                ? {
+                    name: getValue(itemSrc, ['_Name']),
+                    fees: [{ fieldName: 'common', totalFee: getValue(itemSrc, ['_Total']) }],
+                    feeCode: getValue(itemSrc, ['_Code']),
+                    remark: getValue(itemSrc, ['_Remark'])
+                }
+                : {
+                    name: getValue(itemSrc, ['_Name']),
+                    unit: getValue(itemSrc, ['_Unit']),
+                    quantity: getValue(itemSrc, ['_Quantity']),
+                    calcBase: getValue(itemSrc, ['_QtyFormula']),
+                    feeRate: getValue(itemSrc, ['_Rate']),
+                    fees: [{ fieldName: 'common', unitFee: getValue(itemSrc, ['_Price']), totalFee: getValue(itemSrc, ['_Total']) }],
+                    feeCode: getValue(itemSrc, ['_Code']),
+                    remark: getValue(itemSrc, ['_Remark'])
+                };
+            return extendAttrs ? Object.assign(source, extendAttrs) : source;
+        }
+        // 提取数据
+        function extractData(sundry, srcName, fields, groupExtend, itemExtend) {
+            const src = getValue(sundry, srcName);
+            return extractItemsRecur(src, fields, (itemSrc, curField) => {
+                return curField[0] === fields[0][0]
+                    ? extractGroupOrItem(itemSrc, true, groupExtend)
+                    : extractGroupOrItem(itemSrc, false, itemExtend);
+            });
+        }
+        // TODO 材料设备暂估价明细
+    }
+    // 提取税金
+    function extractTax(tenderSrc) {
+        const taxSrc = getValue(tenderSrc, ['Tax']);
+        const itemsSrc = arrayValue(taxSrc, ['TaxItem']);
+        return {
+            ...extractTaxItem(taxSrc),
+            items: itemsSrc.map(extractTaxItem)
+        };
+        function extractTaxItem(src) {
+            return {
+                name: getValue(src, ['_Name']),
+                calcBase: getValue(src, ['_QtyFormula']),
+                feeRate: getValue(src, ['_Rate']),
+                fees: [{ fieldName: 'common', totalFee: getValue(src, ['_Total']) }],
+                feeCode: getValue(src, ['_Code']),
+                remark: getValue(src, ['_Remark'])
+            };
+        }
+    }
+
+    // 供料方式
+    const Provider = {
+        '1': [commonConstants.supplyType.ZXCG],
+        '2': [commonConstants.supplyType.BFJG],
+        '3': [commonConstants.supplyType.WQJG]
+    };
+
+    // 提取人材机汇总相关
+    function extractGLJSummary(tenderSrc) {
+        const taxType = getValue(tenderSrc, ['_TaxModel']); // 计税方式
+        const gljListSrc = arrayValue(tenderSrc, ['LabourMaterialsEquipmentsMachinesSummary']);
+        // 人材机汇总
+        return gljListSrc.map(extractGLJ);
+
+        // 获取原始编码
+        function getOriginalCode(code) {
+            //编码后面有-\d+的形式,去掉-\d+取前面的字符串作为原始代码
+            return code.replace(/(.*)-\d+$/, '$1');
+        }
+        // TODO (不靠谱) 获取人材机类型数据
+        // 导入的源文件没有细化区分人材机类型,这里只是暂时大概给个值。后续会在后端与标准人材机进行配对。也因此无法准确处理补充人材机
+        function getTypeData(gljSrc) {
+            const concrete = getBool(getValue(gljSrc, ['_Concrete']));
+            if (concrete) {
+                return { type: 205, shorName: '商砼' };
+            }
+            switch (type) {
+                case '6':
+                    return { type: 202, shorName: '砼' };
+                case '7':
+                    return { type: 301, shorName: '机' };
+                case '15':
+                    return { type: 6, shortName: '管' };
+                default:
+                    return { type: 201, shortName: '材' };
+            }
+        }
+        // 根据计税方式获取价格,一般计税对应不含税,简易对应含税
+        function getPriceByTaxType(gljSrc, taxType) {
+            return taxType === TaxType.NORMAL
+                ? {
+                    base_price: getValue(gljSrc, ['_NoTaxOrgPrice']),
+                    market_price: getValue(gljSrc, ['_NoTaxPrice'])
+                }
+                : {
+                    base_price: getValue(gljSrc, ['_TaxOrgPrice']),
+                    market_price: getValue(gljSrc, ['_TaxPrice'])
+                };
+        }
+        // 提取组成物
+        function extractRatios(gljSrc) {
+            const ratiosSrc = arrayValue(gljSrc, ['LabourMaterialsEquipmentsMachinesElement']);
+            countData += ratiosSrc.length;
+            return ratiosSrc.map(src => ({
+                code: getValue(src, ['_Number']),
+                consumption: getValue(src, ['_Quantity'])
+            }));
+        }
+        // 提取项目人材机
+        function extractGLJ(gljSrc) {
+            countData.projectGLJCount++;
+            const code = getValue(gljSrc, ['_Number']);
+            return {
+                code,
+                original_code: getOriginalCode(code),
+                name: getValue(gljSrc, ['_Name']),
+                specs: getValue(gljSrc, ['_Specification']),
+                unit: getValue(gljSrc, ['_Unit']),
+                ...getTypeData(gljSrc),
+                ...getPriceByTaxType(gljSrc, taxType), // 软件中项目人材机是没有价格的,只是为了后续处理单价文件
+                is_main_material: getBool(getValue(gljSrc, ['_MainMaterial'])),
+                is_evaluate: getBool(getValue(gljSrc, ['_ProvisionalMaterial'])),
+                supply: Provider[getValue(gljSrc, ['_Provider'])],
+                delivery: getValue(gljSrc, ['_Delivery']),
+                delivery_address: getValue(gljSrc, ['_Location']),
+                originPlace: getValue(gljSrc, ['_ProducingArea']),
+                vender: getValue(gljSrc, ['_Supplier']),
+                qualityGrace: getValue(gljSrc, ['_Character']),
+                remark: getValue(gljSrc, ['_Remark']),
+                ratios: extractRatios(gljSrc)
+            };
 
+        }
+    }
+    // 提取承包人材料
+    function extractContractorList(tenderSrc) {
+        const gljListSrc = arrayValue(tenderSrc, ['LabourMaterialsEquipmentsMachinesSummary']);
+        // 提取造价信息差额调整法
+        function extractDifferentiaGLJ(gljSrc) {
+            return {
+                code: getValue(gljSrc, ['_Number']),
+                name: getValue(gljSrc, ['_Name']),
+                specs: getValue(gljSrc, ['_Specification']),
+                unit: getValue(gljSrc, ['_Unit']),
+                quantity: getValue(gljSrc, ['_Quantity']),
+                riskCoe: getValue(gljSrc, ['_ProviderExp']),
+                standardPrice: getValue(gljSrc, ['_ProviderBase']),
+                market_price: getValue(gljSrc, ['_投标单价']),
+                remark: getValue(gljSrc, ['_备注']),
+            }
+        }
+        // 提取价格指数调整法
+
+    }
 
     /**
      * 解压cos、zip文件