浏览代码

广东接口转换数据

vian 5 年之前
父节点
当前提交
99129195a5

+ 1 - 1
modules/users/models/user_model.js

@@ -388,7 +388,7 @@ class UserModel extends BaseModel {
 
     async getContacts(userID) {
         const user = await this.model.findOne({_id: mongoose.Types.ObjectId(userID)}, 'contacts').lean();
-        if (!user) {
+        if (!user || !user.contacts || !user.contacts.length) {
             return [];
         }
         const userIDList = user.contacts.map(item => mongoose.Types.ObjectId(item.userID));

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

@@ -165,8 +165,8 @@ const importXMLBase = (() => {
             const itemsSrc = arrayValue(src, field);
             if (itemsSrc.length) {
                 const items = itemsSrc.map(itemSrc => {
-                    const obj = extractFuc(itemSrc, curField);
-                    obj.items = getItemsRecur(itemSrc, fields, extractFuc);
+                    const obj = extractFuc(itemSrc, field);
+                    obj.items = extractItemsRecur(itemSrc, fields, extractFuc);
                     return obj;
                 });
                 rst.push(...items);

+ 2 - 1
web/building_saas/pm/html/project-management.html

@@ -1018,7 +1018,7 @@
 <script src="/public/billsUtil.js"></script>
 <script src="/public/common_constants.js"></script>
 <script src="/web/building_saas/main/js/models/importStdInterfaceBase.js"></script>
-<script src="/web/building_saas/main/js/models/importStandardInterface.js"></script>
+<!-- <script src="/web/building_saas/main/js/models/importStandardInterface.js"></script> -->
 <script src="/web/building_saas/pm/js/pm_ajax.js"></script>
 <script src="/web/building_saas/pm/js/pm_newMain.js"></script>
 <script src="/web/building_saas/pm/js/pm_import.js"></script>
@@ -1031,6 +1031,7 @@
 <!-- endinject -->
 <% if (overWriteUrl != undefined) { %>
     <script type="text/javascript" src="<%= overWriteUrl%>"></script>
+    <script type="text/javascript" src="<%= overWriteUrl.slice(0, -3) + '_import.js' %>"></script>
 <% } %>
 
 </body>

+ 2 - 1
web/building_saas/pm/js/pm_newMain.js

@@ -386,7 +386,8 @@ const projTreeObj = {
             name: '导入招投标接口文件',
             icon: 'fa-cloud-upload',
             visible: function () {
-                return compilationData && compilationData.name === '重庆定额(2018)';
+                //return compilationData && compilationData.name === '重庆定额(2018)';
+                return true;
             },
             callback: function () {
                 $('#importInterface').modal('show');

+ 1 - 1
web/common/html/header.html

@@ -60,7 +60,7 @@
                     <a class="dropdown-item" href="#">重庆市2008定额说明</a>-->
                     <!--<a class="dropdown-item" href="/web/common/html/pdfViewer.html?type=userGuide" target="_blank">用户手册</a>
                     <a class="dropdown-item" href="/web/common/html/pdfViewer.html?type=upgradeGuide" target="_blank">升级说明</a>-->
-                    <a class="dropdown-item" href="http://h.zhzdwd.com/gitbook/yun" target="_blank">用户手册</a>
+                    <a class="dropdown-item" href="http://doc.zhzdwd.com/docs/dsk_yhsc" target="_blank">用户手册</a>
                     <a class="dropdown-item" href="/public/share/upgradeGuide/upgradeGuide.pdf" target="_blank">升级说明</a>
                     <a class="dropdown-item" href="https://smartcost.com.cn/" target="_blank">纵横官网</a>
                     <!--  <a class="dropdown-item" href="#">动画教程</a>-->

+ 1 - 1
web/building_saas/main/js/models/importStandardInterface.js

@@ -194,7 +194,7 @@ const importXML = (() => {
                 gljSummary: loadGljSummary(src),
                 differentiaSummary: loadDifferentiaSummary(src),//承包人材料差额法表
                 exponentialSummary: loadExponentialSummary(src),//承包人材料指数法表
-                evalBidSummary: loadEvalBidSummary(src),    //评标材料表
+                evalBidSummary:   loadEvalBidSummary(src),    //评标材料表
                 evalSummary: loadEvalSummary(src) // 暂估价材料表
             };
         });

+ 232 - 39
web/over_write/js/guangdong_2018_import.js

@@ -43,13 +43,19 @@ const importXML = (() => {
         unitPriceFileCount: 0,  //单价文件数量
     };
 
+
+    /* 
+     * 从导入的xml文件中提取有用的数据
+     *
+    */
+
     // 建设项目
     function extractProject(xmlObjMap) {
         Object.keys(countData).forEach(key => countData[key] = 0); // 清缓存
         countData.projectCount++;
         const projectXMLObj = xmlObjMap['Project.xml'];
         const projectSrc = getValue(projectXMLObj, ['ConstructionProject']);
-        importFileKind = FileKind[getValue(source, ['_FileKind'])]; // 标记当前导入的文件类型
+        importFileKind = FileKind[getValue(projectSrc, ['_FileKind'])]; // 标记当前导入的文件类型
         const rst = {
             projectType: projectType.Project,
             name: getValue(projectSrc, ['_Name']),
@@ -59,6 +65,13 @@ const importXML = (() => {
             },
             basicInformation: extractBasicInfo(projectSrc)
         };
+        countData.unitPriceCount = countData.projectGLJCount;
+        if (importFileKind !== FileKind.tender) {
+            countData = {
+                projectCount: countData.projectCount,
+                unitPriceFileCount: countData.unitPriceFileCount
+            };
+        }
         return rst;
     }
     // 从xml对象中提取基本信息相关
@@ -158,10 +171,12 @@ const importXML = (() => {
                 engineering: getValue(src, ['_ProjectType']),
                 projectFeature: extractProjectFeature(src),
                 workSummary: extractWorkSummary(src),
-                fbfx: extractFBFX,
-                csxm: extractCSXM,
-                other: extractOther,
-                tax: extractTax,
+                fbfx: extractFBFX(src),
+                csxm: extractCSXM(src),
+                other: extractOther(src),
+                tax: extractTax(src),
+                ...extractGLJSummary(src),
+                bidEvaluationSummary: extractBidEvaluationSummary(src)
             };
         });
     }
@@ -175,23 +190,29 @@ const importXML = (() => {
     }
     // 提取大项费用
     function extractWorkSummary(tenderSrc) {
-        const summaryList = arrayValue(tenderSrc, ['UnitWorksSummary']);
-        return summaryList.map(src => {
+        const summarySrc = getValue(tenderSrc, ['UnitWorksSummary']);
+        const fields = [['UnitWorksSummaryGroup'], ['UnitWorksSummaryItem']];
+        return extractItemsRecur(summarySrc, fields, (src, curField) => {
             const item = {
                 code: getValue(src, ['_Number']),
                 name: getValue(src, ['_Name']),
                 quantity: getValue(src, ['_Quantity']),
-                calcBase: getValue(src, ['_QtyFormula']),
                 remark: getValue(src, ['_Remark']),
-                feeCode: getValue(src, ['_Code']) //费用字典
+                feeCode: getValue(src, ['_Code']), //费用字典
+                fees: [{
+                    fieldName: 'common', totalFee: getValue(src, ['_Total']) || '0',
+                    unitFee: getValue(src, ['_TechnicalAndEconomicIndex']) || '0'
+                }]
             };
-            if (importFileKind === FileKind.tender) { // 投标
+            if (curField[0] === fields[1][0]) {
+                item.calcBase = getValue(src, ['_QtyFormula']);
                 item.feeRate = getValue(src, ['_Rate']);
-                item.fees = [{
-                    fieldName: 'common', totalFee: getValue(itemSrc, ['_Total']) || '0',
-                    unitFee: getValue(src, ['_TechnicalAndEconomicIndex']) || '0'
-                }];
             }
+            if (importFileKind !== FileKind.tender) {
+                delete item.feeRate
+                delete item.fees;
+            }
+            return item;
         });
     }
     // 从src子项的SummaryOfBasicCost中获取一部分费用
@@ -264,6 +285,7 @@ const importXML = (() => {
             mainBills: getBool(getValue(workElementSrc, ['_Major'])),
             feeCode: getValue(workElementSrc, ['_Code']),
             remark: getValue(workElementSrc, ['_Remark']),
+            rations: extractRations(workElementSrc)
         };
         // 投标和控制价,需要导入最高限价
         if ([FileKind.tender, FileKind.control].includes(importFileKind)) {
@@ -280,15 +302,23 @@ const importXML = (() => {
                     { fieldName: 'equipment', unitFee: getValue(workElementSrc, ['_EquipmentPrice']) },
                 ];
                 bills.fees = mergeFees(fees, summaryFees);
-                // 输出定额数据
-                bills.rations = extractRations(workElementSrc);
             }
         }
+        return bills;
         // 获取项目特征文本
         function getItemCharacterText(attr) {
+            // 去掉除换行符以外的空白符
+            const newLine = '{newLine}';
+            attr = attr
+                .replace(/[\r\n]/g, newLine)
+                .replace(/\s/g, '')
+                .replace(new RegExp(newLine, 'g'), '\n');
             const matchStrs = ['&#xA;', ';'];
             const matchStr = matchStrs.find(str => attr.includes(str));
-            return attr.replace(new RegExp(matchStr, 'g'), '\n');
+            if (matchStr) {
+                attr = attr.replace(new RegExp(matchStr, 'g'), '\n');
+            }
+            return attr;
         }
         // 获取清单项目特征窗口数据
         function getItemCharacter(itemText) {
@@ -325,6 +355,9 @@ const importXML = (() => {
     }
     // 提取定额
     function extractRations(workElementSrc) {
+        if (importFileKind !== FileKind.tender) {
+            return [];
+        }
         // 正常情况下定额肯定是在WorkContent内的,但是也做定额不在WorkContent内的处理(外层定额)
         const rations = [];
         let serialNo = 1;
@@ -353,7 +386,7 @@ const importXML = (() => {
                 '1': true,
                 '2': false
             };
-            const isItemIncrease = itemIncreaseMap[getValue(rationsSrc, ['IncFeeKind'])];
+            const isItemIncrease = itemIncreaseMap[getValue(rationSrc, ['IncFeeKind'])];
             if (isItemIncrease) {
                 return rationType.itemIncrease;
             }
@@ -409,6 +442,7 @@ const importXML = (() => {
             const feesFromCalcItem = getFeesFromCalculationOfItem(rationSrc);
             ration.fees = mergeFees(fees, feesFromCalcItem);
             ration.rationGLJs = extractRationGLJs(rationSrc);
+            return ration;
         }
     }
     // 提取措施项目
@@ -435,23 +469,24 @@ const importXML = (() => {
         const sundryCosts = getValue(sundry, ['SundryCosts']);
         // 其他项目汇总费用
         const sundryFees = [{ fieldName: 'common', totalFee: getValue(sundryCosts, ['_Total']) }];
+        debugger;
         return {
-            fees: sundryFees,
+            fees: importFileKind === FileKind.tender ? 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']) }),
+                { engineeringContent: ['_Content'] }, { engineeringContent: ['_Content'] }),
             dayWork: extractData(sundry, 'DayWorkRate', [['DayWorkRateGroup'], ['DayWorkRateItem']]),
-            mainContractor: extractData(sundry, 'MainContractorAttendance', [['MainContractorAttendanceGroup'], ['MainContractorAttendanceItem']], { serviceContent: getValue(itemSrc, ['_Content']) }),
+            mainContractor: extractData(sundry, 'MainContractorAttendance', [['MainContractorAttendanceGroup'], ['MainContractorAttendanceItem']], { serviceContent: ['_Content'] }),
             claim: extractData(sundry, 'ClaimsCost', [['ClaimsCostGroup'], ['ClaimsCostItem']]),
             visa: extractData(sundry, 'SiteInstructionCost', [['SiteInstructionCostGroup'], ['SiteInstructionCostItem']]),
         };
         // 提取标题和明细
-        function extractGroupOrItem(src, isGroup = true, extendAttrs = null) {
+        function extractGroupOrItem(itemSrc, isGroup = true, extendAttrs = null) {
             const source = isGroup
                 ? {
                     name: getValue(itemSrc, ['_Name']),
-                    fees: [{ fieldName: 'common', totalFee: getValue(itemSrc, ['_Total']) }],
+                    fees: importFileKind === FileKind.tender ? [{ fieldName: 'common', totalFee: getValue(itemSrc, ['_Total']) }] : [],
                     feeCode: getValue(itemSrc, ['_Code']),
                     remark: getValue(itemSrc, ['_Remark'])
                 }
@@ -461,16 +496,28 @@ const importXML = (() => {
                     quantity: getValue(itemSrc, ['_Quantity']),
                     calcBase: getValue(itemSrc, ['_QtyFormula']),
                     feeRate: getValue(itemSrc, ['_Rate']),
-                    fees: [{ fieldName: 'common', unitFee: getValue(itemSrc, ['_Price']), totalFee: getValue(itemSrc, ['_Total']) }],
+                    fees: importFileKind === FileKind.tender ? [{ 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);
+        function extractData(sundry, srcName, fields, groupExtendMap, itemExtendMap) {
+            const src = getValue(sundry, [srcName]);
             return extractItemsRecur(src, fields, (itemSrc, curField) => {
+                const groupExtend = groupExtendMap
+                    ? Object.keys(groupExtendMap).reduce((acc, key) => {
+                        acc[key] = getValue(itemSrc, groupExtendMap[key]);
+                        return acc;
+                    }, {})
+                    : null;
+                const itemExtend = itemExtendMap
+                    ? Object.keys(itemExtendMap).reduce((acc, key) => {
+                        acc[key] = getValue(itemSrc, itemExtendMap[key]);
+                        return acc;
+                    }, {})
+                    : null;
                 return curField[0] === fields[0][0]
                     ? extractGroupOrItem(itemSrc, true, groupExtend)
                     : extractGroupOrItem(itemSrc, false, itemExtend);
@@ -491,7 +538,7 @@ const importXML = (() => {
                 name: getValue(src, ['_Name']),
                 calcBase: getValue(src, ['_QtyFormula']),
                 feeRate: getValue(src, ['_Rate']),
-                fees: [{ fieldName: 'common', totalFee: getValue(src, ['_Total']) }],
+                fees: importFileKind === FileKind.tender ? [{ fieldName: 'common', totalFee: getValue(src, ['_Total']) }] : [],
                 feeCode: getValue(src, ['_Code']),
                 remark: getValue(src, ['_Remark'])
             };
@@ -505,12 +552,20 @@ const importXML = (() => {
         '3': [commonConstants.supplyType.WQJG]
     };
 
-    // 提取人材机汇总相关
+    // 提取人材机汇总相关(人材机汇总表、承包材料表)
     function extractGLJSummary(tenderSrc) {
+        const initData = { gljSummary: [], differentiaSummary: [], exponentialSummary: [] };
+        if (importFileKind !== FileKind.tender) {
+            return initData;
+        }
         const taxType = getValue(tenderSrc, ['_TaxModel']); // 计税方式
         const gljListSrc = arrayValue(tenderSrc, ['LabourMaterialsEquipmentsMachinesSummary']);
-        // 人材机汇总
-        return gljListSrc.map(extractGLJ);
+        return gljListSrc.reduce((acc, gljSrc) => {
+            acc.gljSummary.push(extractGLJ(gljSrc));
+            acc.differentiaSummary.push(extractDifferentiaGLJ(gljSrc));
+            acc.exponentialSummary.push(extractExponentialGLJ(gljSrc));
+            return acc;
+        }, initData);
 
         // 获取原始编码
         function getOriginalCode(code) {
@@ -524,6 +579,7 @@ const importXML = (() => {
             if (concrete) {
                 return { type: 205, shorName: '商砼' };
             }
+            const type = getValue(gljSrc, ['_Kind']);
             switch (type) {
                 case '6':
                     return { type: 202, shorName: '砼' };
@@ -550,7 +606,7 @@ const importXML = (() => {
         // 提取组成物
         function extractRatios(gljSrc) {
             const ratiosSrc = arrayValue(gljSrc, ['LabourMaterialsEquipmentsMachinesElement']);
-            countData += ratiosSrc.length;
+            countData.ratioCount += ratiosSrc.length;
             return ratiosSrc.map(src => ({
                 code: getValue(src, ['_Number']),
                 consumption: getValue(src, ['_Quantity'])
@@ -579,12 +635,7 @@ const importXML = (() => {
                 remark: getValue(gljSrc, ['_Remark']),
                 ratios: extractRatios(gljSrc)
             };
-
         }
-    }
-    // 提取承包人材料
-    function extractContractorList(tenderSrc) {
-        const gljListSrc = arrayValue(tenderSrc, ['LabourMaterialsEquipmentsMachinesSummary']);
         // 提取造价信息差额调整法
         function extractDifferentiaGLJ(gljSrc) {
             return {
@@ -595,13 +646,153 @@ const importXML = (() => {
                 quantity: getValue(gljSrc, ['_Quantity']),
                 riskCoe: getValue(gljSrc, ['_ProviderExp']),
                 standardPrice: getValue(gljSrc, ['_ProviderBase']),
-                market_price: getValue(gljSrc, ['_投标单价']),
-                remark: getValue(gljSrc, ['_备注']),
-            }
+                market_price: getPriceByTaxType(gljSrc, taxType).market_price,
+                remark: getValue(gljSrc, ['_Remark']),
+            };
         }
         // 提取价格指数调整法
+        function extractExponentialGLJ(gljSrc) {
+            return {
+                code: getValue(gljSrc, ['_Number']),
+                name: getValue(gljSrc, ['_Name']),
+                specs: getValue(gljSrc, ['_Specification']),
+                varWeight: getValue(gljSrc, ['_Weight']),
+                FO: getValue(gljSrc, ['_BasicPrice']),
+                FI: getValue(gljSrc, ['_CurrentPrice']),
+                remark: getValue(gljSrc, ['_Remark'])
+            };
+        }
+    }
+    // 提取评标材料
+    function extractBidEvaluationSummary(tenderSrc) {
+        if (importFileKind !== FileKind.tender) {
+            return [];
+        }
+        const srcList = arrayValue(tenderSrc, ['BidEvaluationMainMaterial']);
+        return srcList.map(src => ({
+            seq: getValue(gljSrc, ['_Code']),
+            code: getValue(gljSrc, ['_Number']),
+            name: getValue(gljSrc, ['_Name']),
+            specs: getValue(gljSrc, ['_Specification']),
+            unit: getValue(gljSrc, ['_Unit']),
+            quantity: getValue(gljSrc, ['_Quantity']),
+            market_price: getValue(gljSrc, ['_Price']),
+            originPlace: getValue(gljSrc, ['_ProducingArea']),
+            vender: getValue(gljSrc, ['_Supplier']),
+            remark: getValue(gljSrc, ['_Remark'])
+        }));
+    }
+
 
+    /* 
+     * 转换从xml提取的数据,转换成软件所需的数据结构
+     *
+    */
+    async function transformData(extractedData) {
+        const IDPlaceholder = await ajaxPost('/pm/import/getProjectPlaceholder', countData);
+        extractedData.ID = IDPlaceholder.project++;
+        // 最终上传到服务器的转换后的数据
+        const transformedData = {
+            ID: extractedData.ID,
+            ParentID: extractedData.ParentID,
+            NextSiblingID: extractedData.NextSiblingID,
+            preID: extractedData.preID,
+            name: extractedData.name,
+            basicInformation: extractedData.basicInformation,
+            projType: extractedData.projType,
+            property: extractedData.property,
+            shareInfo: [],
+            engs: []
+        };
+        // 所有的清单模板库ID
+        const allTemplateLibIDs = [];
+        extractedData.engs.forEach(eng => {
+            eng.tenders.forEach(tender => {
+                let templateLibID = tender.property.templateLibID;
+                if (!allTemplateLibIDs.includes(templateLibID)) {
+                    allTemplateLibIDs.push(templateLibID);
+                }
+            });
+        });
+        // 模板映射:{[templateLibID]: data}
+        const templateMapping = await ajaxPost('/template/bills/api/getNeedfulTemplate', { allTemplateLibIDs });
+        for (let i = 0; i < extractedData.engs.length; i++) {
+            const curEng = extractedData.engs[i];
+            const preEng = transformedData.engs[i - 1];
+            curEng.ID = IDPlaceholder.project++;
+            curEng.ParentID = extractedData.ID;
+            curEng.NextSiblingID = -1;
+            if (preEng) {
+                preEng.NextSiblingID = curEng.ID;
+            }
+            const engData = {
+                ID: curEng.ID,
+                ParentID: curEng.ParentID,
+                NextSiblingID: curEng.NextSiblingID,
+                code: curEng.code,
+                name: curEng.name,
+                projType: curEng.projType,
+                shareInfo: [],
+                tenders: []
+            };
+            transformedData.engs.push(engData);
+            for (let j = 0; j < curEng.tenders.length; j++) {
+                const curTender = curEng.tenders[j];
+                const preTender = engData.tenders[j - 1];
+                curTender.ID = IDPlaceholder.project++;
+                curTender.ParentID = curEng.ID;
+                curTender.NextSiblingID = -1;
+                curTender.property.unitPriceFile.id = IDPlaceholder.unitPriceFile++;
+                if (preTender) {
+                    preTender.tender.NextSiblingID = curTender.ID;
+                }
+                // 项目清单模板(后台清单模板中提取含有固定类别的数据)
+                const projectBills = _.cloneDeep(templateMapping[curTender.property.templateLibID]);
+                debugger;
+                // 重设模板树结构数据
+                BILLS_UTIL.resetTreeData(projectBills, uuid.v1);
+                console.log(projectBills);
+                const tenderData = transformTender(curTender, IDPlaceholder, projectBills);
+                tenderData.tender.property.rootProjectID = transformedData.ID;
+                engData.tenders.push(tenderData);
+            }
+        }
+        return transformedData;
+    }
+
+    // 转换单位工程的数据(直接可插入数据库的数据),返回{tender: {}, bills: [], ration: [], rationGLJ: [], projectGLJ: [], unitPrice: [], mixRatio: []}
+    function transformTender(tenderData, IDPlaceholder, projectBills) {
+        const detailData = transformDetail(tenderData, IDPlaceholder, projectBills);
+        // 提取需要插入的单位工程数据
+        const transformedTender = {
+            ID: tenderData.ID,
+            ParentID: tenderData.ParentID,
+            NextSiblingID: tenderData.NextSiblingID,
+            code: tenderData.code,
+            name: tenderData.name,
+            projType: tenderData.projType,
+            property: tenderData.property,
+            projectFeature: tenderData.projectFeature,
+            engineering: tenderData.engineering,
+            defaultRationLib: tenderData.defaultRationLib,
+            rationLibIDs: tenderData.rationLibIDs,
+            gljLibIDs: tenderData.gljLibIDs,
+            shareInfo: []
+        };
+        transformedTender.property.gljAdjustType = AdjustType.info;
+        detailData.tender = transformedTender;
+        return detailData;
     }
+    // 转换清单
+    function transformBills(tenderData, IDPlaceholder, projectBills) {
+
+    }
+    // 转换详细的项目数据,清单、定额、定额人材机、项目人材机、单价文件等
+    function transformDetail() {
+
+    }
+
+
 
     /**
      * 解压cos、zip文件
@@ -628,6 +819,7 @@ const importXML = (() => {
         }
         const xmlObjMap = {};
         for (const fileName in fileMap) {
+            // x2js转换xml使用了DomParser接口,会将一些字符实体进行转义。若不想被自动转义,则需要调用escapeXMLEntity
             const xmlStr = escape ? util.escapeXMLEntity(fileMap[fileName]) : fileMap[fileName];
             //将xml格式良好的字符串转换成对象
             const x2js = new X2JS();
@@ -648,5 +840,6 @@ const importXML = (() => {
     return {
         accept,
         extractData,
+        transformData,
     }
 })();