diff --git a/ats/analysis/ATS_AIM_customer_data_analysis.js b/ats/analysis/ATS_AIM_customer_data_analysis.js
index 7ed6495eaccad1ec8c73f4329a33cb0092b6b9d6..4f9daec3edba30c5e50e3120e13d00a84299cd45 100644
--- a/ats/analysis/ATS_AIM_customer_data_analysis.js
+++ b/ats/analysis/ATS_AIM_customer_data_analysis.js
@@ -3,6 +3,24 @@
     DESCRIPTION: 客户数据分析
     PARAMETER:
 	[
+        {
+            name : 'pcs_step',
+			title : 'pcsStep名',
+			type : 'LineEdit',
+			property : {tool_tip : 'pcs step名,默认是cad'}
+        },
+        {
+            name : 'array_step',
+			title : 'arrayStep名',
+			type : 'LineEdit',
+			property : {tool_tip : 'array step名,默认是stp'}
+        },
+        {
+            name : 'erf',
+			title : 'erf名称',
+			type : 'LineEdit',
+			property : {tool_tip : 'erf名称'}
+        },
         {
             name : 'auto_save',
 			title : '自动保存',
@@ -32,7 +50,6 @@
 		  <br>
 	</body></html>	
 */
-console.log("=============================================>anaysis_start");
 // 引入模块 包
 var $ = require('topcam.scriptfunc').argv();
 var fs = require('fs');
@@ -60,9 +77,23 @@ if ($.hasOwnProperty('script_parameter')){
 	PAR = JSON.parse($.script_parameter);
 }
 try {
-    var job = Job;
-    var pcs_step = "cad", array_step = "stp";
+    console.log("=============================================>anaysis_start");
+    var par = PAR;
+    if(par.erf == ""){delete PAR.erf}
+    // if(par.erf == ""){par.erf = "GBM_0.50z"}
+
+	if(_.isEmpty(Job)) throw "没有传入料号名!";
+    var job = Job.toLowerCase();
+    // 检查料号是否能够check out
+	if(GEN.checkInout({job:job,mode:"test"}) != 0){ throw "the job check" }
+    GEN.checkInout({job:job,mode:"out"});
+    var pcs_step = par.pcs_step == "" ? "cad" : par.pcs_step;
+    var array_step = par.array_step == "" ? "stp" : par.pcs_step;
     var matrix = UPLOAD_LAYER_MATRIX({job:job})  // 分析matrix 获得分析后的matrix信息
+    var step_list = GEN.getStepList({job:job})
+    console.log("===================>steplist:"+_.toString(step_list))
+    if(step_list.indexOf(pcs_step)<0){throw "can not find pcsstep"}
+    if(step_list.indexOf(array_step)<0){array_step = false}
     console.log("===================================> 1matrix")
     var analysis_obj = analysis({job:job,jobId:JobId,pcs_step:pcs_step,array_step:array_step,matrix:matrix})
     var config = {
@@ -108,6 +139,7 @@ try {
     var jobInfo = {}
     Object.keys(config.jobInfo).forEach(function(key){
         var props = config.jobInfo[key];
+        console.log("===================================> 2analysis_obj:key:"+key)
         if(props){
             try {
                 if(props.hasOwnProperty("api") && props.hasOwnProperty("props")){
@@ -127,18 +159,14 @@ try {
 
     // 过滤掉料号信息的 _todo 和 _error
     for (var key in jobInfo) {
+        if(jobInfo[key]==="yes"){jobInfo[key] = "Yes"}
+        if(jobInfo[key]==="no"){jobInfo[key] = "No"}
         if(jobInfo[key] === "_todo" || jobInfo[key] === "_error"){
             delete jobInfo[key]
         }
     }
     console.log("===================================> 4 save job info")
 
-    // 上传jobInfo  IKM版本
-    // IKM.save_job_info({
-    //     jobid: JobId,
-    //     jobinfohash:jobInfo
-    // })
-    // 上传jobInfo  topjs3版本
     save_job_info({
         jobid: JobId,
         jobinfohash: jobInfo
@@ -190,7 +218,8 @@ try {
                     where:{job_id:JobId, layer_name: layer,tool_num: key}
                 })
             });
-            if(/done/ig.test(id)){
+            console.log("=========>drillid:"+id)
+            if(/done/ig.test(id) || !id){
                 db.query("",function(q){
                     return q.insertRow({
                         table:'pdm_job_cam_drill',  
@@ -211,13 +240,53 @@ try {
         })
     })
 
-    console.log("===================================> 6 layer info")
-    // 分析layer info
+    console.log("===================================> 6 smd info")
+    
+    // smd
+    var smdInfo;
+    try {
+        if(!analysis_obj.matrixInfo.mOuters.solderL){throw "no mask"}
+        smdInfo = smdAnalysis({job:job,steplist:[pcs_step],layers:analysis_obj.matrixInfo.mOuters,attr:".smd"})
+    } catch (msg) {
+        console.log("smdInfo:error:"+msg)
+        smdInfo = {}
+    }
+
+    // bga
+    console.log("===================================> 7 bga info")
+    var bgaInfo;
+    try {
+        if(!analysis_obj.matrixInfo.mOuters.solderL){throw "no mask"}
+        bgaInfo = bgaAnalysis({job:job,steplist:[pcs_step],layers:analysis_obj.matrixInfo.mOuters,attr:".bga"})
+    } catch (msg) {
+        console.log("bgaInfo:error:"+msg)
+        bgaInfo = {}
+    }
+    if(JSON.stringify(bgaInfo)  == "{}"){
+        console.log("can not find .bga attr")
+    }
+    // 保存
+    console.log("===================================> 8 save bga smd info")
+    var save_info = [smdInfo, analysis_obj.jobInfo.laser_info,bgaInfo];  // 保存 smd  和  bga数据
+    save_info.forEach(function(item){
+        if(JSON.stringify(item)!= "{}" && item){
+            Object.keys(item).forEach(function(key){
+                var val = item[key]
+                save_layerinfo({
+                    jobid: JobId,
+                    layer: key,
+                    layerinfohash: val
+                })
+            })
+        }
+    })
+    console.log("===================================> 9 copper_percent signal drill")
 
+    // 分析layer info
     var stepList = [pcs_step];
     var oChecklistName = "mychecklist"
-    var signalLayers = analysis_obj.matrixInfo.mSignal.map(function(v){return v.name})
-    var drillLayers = analysis_obj.matrixInfo.mDrill.map(function(v){return v.name})
+    var signalLayers = analysis_obj.matrixInfo.mSignals.map(function(v){return v.name})
+    var drillLayers = analysis_obj.matrixInfo.mDrills.map(function(v){return v.name})
     var info = {
         min_line_width: ["line"],
         min_line_spacing: ["l2l"],
@@ -227,41 +296,41 @@ try {
     }
     stepList.forEach(function(step){
         GEN.openStep({ job: job, name: step })
+        
         GEN.clearLayers()
         GEN.affectedLayer({ affected: 'no', mode: 'all' })
         // 创建chklist并运行 如果chklist存在先删除
         if (GEN.isChklistExists({ job: job, step: step, chklist: oChecklistName })) {
             GEN.COM("chklist_delete", { chklist: oChecklistName })
         }
+        var tmpitem = {
+            name: "signal_layer_checks",
+            nact: 1,
+            action: "valor_analysis_signal",
+            params: { 
+                pp_layer: ".affected",
+                pp_spacing: 20,
+                pp_selected: "All",
+                pp_r2c: 10,
+                pp_d2c: 15,
+                pp_sliver: 8,
+                pp_min_pad_overlap: 5,
+                pp_check_missing_pads_for_drills: "Yes",
+                pp_use_compensated_rout: "Skeleton",
+                pp_sm_spacing: "Yes"
+            }
+        }
+        if(par.erf){
+            tmpitem.erf = par.erf
+        }
         createChklistAndRun({   // 创建checklist并运行
             layers: signalLayers,
-            items: [{
-                name: "signal_layer_checks",
-                nact: 1,
-                action: "valor_analysis_signal",
-                erf: "S2_conductor_Check",
-                params: {   //  ?
-                    pp_layer: ".affected",
-                    pp_spacing: 20,
-                    pp_selected: "All",
-                    pp_r2c: 10,
-                    pp_d2c: 15,
-                    pp_sliver: 8,
-                    pp_min_pad_overlap: 5,
-                    pp_check_missing_pads_for_drills: "Yes",
-                    pp_use_compensated_rout: "Skeleton",
-                    pp_sm_spacing: "Yes"
-                }
-            }]
+            items: [tmpitem]
         })
+        console.log("===================================> 11 signals analysis")
         // signal层分析结果
         var res = analysisChkAttr({layers:signalLayers, info:info, step:step, job:job, oChecklistName:oChecklistName})
-        // 铜面积
-        var copper_percent_pcs = signalLayers.map(function(v){
-            var tmp = {layer:v}
-            tmp.copper_percent = GEN.copperArea({layer1:v}).percent + "%"
-            return tmp
-        })
+        
         // 钻孔
         var drillToSignals = drillLayers.map(function(v){  // 获取到钻孔层对应的顶层和底层
             var simbols = GEN.getLayerSymsHist({job:job,step:step,layer:v})
@@ -274,8 +343,8 @@ try {
             },[])[0]
             return {layer:v,symbol:symbol,start:matrix[v]["drl_start"],end:matrix[v]["drl_end"]}
         })
+        console.log("===================================> 12 Drill analysis")
         var drillRes = analysisDrill(drillToSignals,step) // 钻孔分析结果
- 
         //  数据入库 
         Object.keys(res).forEach(function(key){
             var val = res[key]
@@ -285,15 +354,6 @@ try {
                 layerinfohash: val
             })
         })
-        copper_percent_pcs.forEach(function(item){
-            save_layerinfo({
-                jobid: JobId,
-                layer: item.layer,
-                layerinfohash: {
-                    copper_percent: item.copper_percent
-                }
-            })
-        })
         drillRes.forEach(function(item){
             save_layerinfo({
                 jobid: JobId,
@@ -304,25 +364,52 @@ try {
                 }
             })
         })
-    })
-
-
-    // smd
-    var smdInfo = smdAnalysis({job:job,steplist:[pcs_step],layers:analysis_obj.matrixInfo.mOuters,attr:".smd"})
-    var save_info = [smdInfo, analysis_obj.jobInfo.laser_info];  // 保存 smd  和  bga数据
-    // 保存
-    console.log("===================================> save layer info")
-    save_info.forEach(function(item){
-        Object.keys(item).forEach(function(key){
-            var val = item[key]
-            save_layerinfo({
-                jobid: JobId,
-                layer: key,
-                layerinfohash: val
-            })
+        // 铜面积
+        console.log("===================================> 13 save copper_percent")
+        // 创建profile
+        var new_martix = GEN.getMatrix({job:job})
+        var profileLayer = Object.keys(new_martix).filter(function(v){
+            return new_martix[v].layer_type=="rout" && new_martix[v].context == "board"
         })
+        if(profileLayer.length){
+            var tmp = profileLayer[0]
+            if(profileLayer.indexOf("outline")>=0){tmp = "outline"}
+            GEN.openStep({job:job,name:pcs_step})
+            GEN.workLayer({name:tmp,display_number:2,clear_before:'yes'})
+            GEN.selAllFeat();
+            var count = GEN.getSelectCount()
+            if(count > 0){
+                GEN.selCreateProfile()
+                GEN.selClearFeature()
+            }
+            GEN.closeStep()
+            var copper_percent_pcs = signalLayers.map(function(v){
+                var tmp = {layer:v}
+                tmp.copper_percent = GEN.copperArea({layer1:v}).percent + "%"
+                return tmp
+            })
+            copper_percent_pcs.forEach(function(item){
+                save_layerinfo({
+                    jobid: JobId,
+                    layer: item.layer,
+                    layerinfohash: {
+                        copper_percent: item.copper_percent
+                    }
+                })
+            })
+        }
     })
 
+    // 保存 
+	if(/yes/ig.test(par.auto_save)){
+		GEN.checkInout({job:job,mode:"out"})  // 结束保存料号 关闭料号
+		GEN.saveJob({ job: job });
+		GEN.checkInout({job:job,mode:"in"})
+		GEN.closeJob({job:job})
+	} else {
+		GEN.checkInout({job:job,mode:"in"})
+	}
+
 
     QDfm.updateRow({
 		table: "pdm_aimdfm_task",
@@ -409,29 +496,15 @@ function UPLOAD_LAYER_MATRIX(props){
 			return new TDataResponse(err, "");\
 		}\
     }';
-    // var ret = IKM.command( func,     // ?? =========================> tmp
-    //     {   job_id :JobId, 
-    //         matrix:matrix,
-    //         layers: Object.keys(matrix).sort(function(a,b){return matrix[a]["row"] - matrix[b]["row"]}), 
-    //         jobcategory:props.jobcategory}, 1);
-	// if (ret.errText) {                    
-	// 	return {
-	// 		jobcategory:props.jobcategory,
-	// 		errText :ret.errText,
-	// 		errCode :ret.errCode,
-	// 	};
-    // }
+  
     return matrix
 }
 function ANALYSIS_STACKUP(props){
     var job = props.job
     if(!props.hasOwnProperty("jobcategory")){ props.jobcategory = 'work' }
     var matrix = GEN.getMatrix({job:job})
-	var layer_count = IKM.get_jobinfo({jobname:JobId,jobcategory:props.jobcategory,jobinfo:'layer_count'});
-    if(!layer_count){
-        layer_count = GEN.getLayerCount({job:job})
-    }
-	IKM.save_job_info({jobid:JobId,jobcategory:props.jobcategory,jobinfohash:{TL_layer_count:layer_count}});
+    var layer_count = GEN.getLayerCount({job:job}) // !
+	save_job_info({jobid:JobId,jobcategory:props.jobcategory,jobinfohash:{TL_layer_count:layer_count}});
 	_.values(matrix).sort(function(a,b){return a.row-b.row}).forEach(function(layer){
         layer.odb_name = layer.name;
 		layer.name = layer.tl_name;
@@ -575,13 +648,32 @@ function save_job_info(props){  // todo 保存料号信息
     var jobinfohash = props.jobinfohash;
     Object.keys(jobinfohash).forEach(function(key){
         var val = jobinfohash[key];
-        db.query("",function(q){
-            return q.insertRow({
-                table:'sys_user',  // todo 
-                data:{jobid:jobid, todo:key, value:val}, // todo
-                return_field:'id',
+        var value = db.query("",function(q){
+            return q.selectValue({
+                table:'pdm_job_jobattr',  
+                field:"value", 
+                where:{job_id:jobid, attr_name: key}
             })
         });
+        console.log("jobid:"+jobid+"==========dbjobvalue:" + val)
+        if(/done/ig.test(value) || !value){
+            db.query("",function(q){
+                return q.insertRow({
+                    table:'pdm_job_jobattr',  // todo 
+                    data:{job_id:jobid, attr_name:key, value:val}, // todo
+                    return_field:'job_id',
+                })
+            });
+        } else if (value != val) {
+            console.log("jobid:"+jobid+"==========update jobvalue:"+value+"->" + val)
+            db.query("",function(q){
+                return q.updateRow({
+                    table:'pdm_job_jobattr',
+                    where:{job_id:jobid, attr_name: key},
+                    data:{value:val},
+                })
+            });
+        }
     })
 }
 function save_layerinfo(props){   // todo 保存层信息
@@ -590,16 +682,34 @@ function save_layerinfo(props){   // todo 保存层信息
     var layerinfohash = props.layerinfohash;
     Object.keys(layerinfohash).forEach(function(key){
         var val = layerinfohash[key];
-        db.query("",function(q){
-            return q.insertRow({
-                table:'sys_user',  // todo 
-                data:{jobid:jobid, layer:layer,key:key , value:val}, // todo
-                return_field:'id',
+        var value = db.query("",function(q){
+            return q.selectValue({
+                table:'pdm_job_layerattr',  
+                field:"value", 
+                where:{job_id:jobid, attr_name: key, layer:layer}
             })
         });
+        console.log("+==========dblayervalue:" + value)
+        if(/done/ig.test(value) || !value){
+            db.query("",function(q){
+                console.log("+==========insertRowlayervalue:layer:"+layer+";attrname:"+key+";value:"+ val)
+                return q.insertRow({
+                    table:'pdm_job_layerattr',  // todo 
+                    data:{job_id:jobid, attr_name:key, value:val, layer:layer}, // todo
+                    return_field:'job_id',
+                })
+            });
+        } else if (value !== val) {
+            db.query("",function(q){
+                console.log("+==========updateRowlayer:layer:"+layer+";attrname:"+key+";value:"+ val)
+                return q.updateRow({
+                    table:'pdm_job_layerattr',
+                    where:{job_id:jobid, attr_name: key},
+                    data:{value:val},
+                })
+            });
+        }
     })
-
-
 }
 function analysis(props){
     var job = props.job || Job;
@@ -781,9 +891,9 @@ function analysis(props){
             if(a.indexOf(b)<0){ a.push(b) }
             return a
         },[])
-        var res = "no"
+        var res = "none"
         if(solder_paste_info.length == 0){
-            res = "no"
+            res = "none"
         } else if (solder_paste_info.length == 1) {
             res = /top/ig.test(solder_paste_info[0]) ?  "top" : "bot"
         } else {
@@ -797,9 +907,9 @@ function analysis(props){
             if(a.indexOf(b)<0){ a.push(b) }
             return a
         },[])
-        var res = "no"
+        var res = "none"
         if(solder_mask_info.length == 0){
-            res = "no"
+            res = "none"
         } else if (solder_mask_info.length == 1) {
             res = /top/ig.test(solder_mask_info[0]) ?  "top" : "bot"
         } else {
@@ -923,28 +1033,31 @@ function smdPitch(props){
         GEN.COM("chklist_delete", { chklist: ck })
     }
     // 创建并运行
+    var tmpItem = {
+        name: "smdPitch",
+        nact: 1,
+        action: "valor_analysis_signal",
+        params: {   
+            pp_layer: ".affected",
+            pp_spacing: 20,
+            pp_selected: "All",
+            pp_r2c: 10,
+            pp_d2c: 15,
+            pp_sliver: 8,
+            pp_min_pad_overlap: 5,
+            pp_check_missing_pads_for_drills: "Yes",
+            pp_use_compensated_rout: "Skeleton",
+            pp_sm_spacing: "Yes",
+            pp_tests: "Spacing\\;SMD",
+            pp_check_missing_pads_for_drills:"Yes"
+        }
+    }
+    if(PAR.erf && PAR.erf != ""){
+        tmpItem.erf = PAR.erf
+    }
     GEN.createChklist({ // 创建checklist
         chklist: ck,
-        items: [{
-            name: "smdPitch",
-            nact: 1,
-            action: "valor_analysis_signal",
-            erf: "S2_conductor_Check",
-            params: {   
-                pp_layer: ".affected",
-                pp_spacing: 20,
-                pp_selected: "All",
-                pp_r2c: 10,
-                pp_d2c: 15,
-                pp_sliver: 8,
-                pp_min_pad_overlap: 5,
-                pp_check_missing_pads_for_drills: "Yes",
-                pp_use_compensated_rout: "Skeleton",
-                pp_sm_spacing: "Yes",
-                pp_tests: "Spacing\\;SMD",
-                pp_check_missing_pads_for_drills:"Yes"
-            }
-        }]
+        items: [tmpItem]
     })
     GEN.chklistShow({ chklist: ck })
     GEN.affectedLayer({ affected: "yes", layer: layer, clear_before: "yes" })
@@ -1083,13 +1196,270 @@ function analysisDrill(par, step){
     return res
 }
 
+function bgaAnalysis(props){
+    var job = props.job
+    var steplist = props.steplist
+    var layers = props.layers;
+    GEN.clearLayers()
+    GEN.affectedLayer({affected:'yes',layer:layers.map(function(v){return v.signalL})})
+    GEN.selectByFilter({attribute:props.attr})
+    var count = GEN.getSelectCount()
+    GEN.affectedLayer({affected:'no',mode:'all'})
+    GEN.selClearFeature()
+    if(count == 0 ) {
+        return {}
+    }
+    var res = {}
+    steplist.forEach(function(step){
+        GEN.openStep({job:job,step:step})
+        layers.forEach(function(layer){
+            // 找出bga 拷贝到辅助层
+            GEN.workLayer({name:layer.signalL,display_number:2,clear_before:'yes'})
+            GEN.selClearFeature()
+            GEN.selectByFilter({attribute:props.attr})
+            var selCount = GEN.getSelectCount()
+            if(selCount>0){
+                var tmp_layer = layer.signalL + "_tmp"
+                selCopyLayer({job:job,layer:tmp_layer})
+                var symbols = GEN.getLayerSymsHist({job:job,layer:tmp_layer,step:step})
+                GEN.workLayer({name:tmp_layer,display_number:2,clear_before:'yes'})
+                // 分析数据
+                var syblist = _.values(symbols).reduce(function(a,b){
+                    if (b.pad > 0 && b.line) {
+                        a.push({symbol:b.symbol, size:Number(b.size)})
+                    }
+                    return a
+                },[])
+                // 找到最小的bga分析
+                var min_symbols = syblist.sort(function(a,b){return a.size-b.size})[0]
+                var min_symbols_info = min_symbols_anal({symbols:min_symbols, job:job, step:step, layer:layer})
+                if (!res.hasOwnProperty(layer.signalL)){
+                    res[layer.signalL] = {}
+                }
+                res[layer.signalL].min_bga_size = min_symbols_info["min_bga_size"]
+                res[layer.signalL].min_bga_openging_size = min_symbols_info["min_bga_openging_size"]
+                res[layer.signalL].min_bga_pitch = min_symbols_info["min_bga_pitch"]
+                // 分析所有BGA
+                var all_bga_min_pitch_info = all_bga_min_pitch_anal({job:job, step:step, layer:tmp_layer,solderLayer:layer.solderL})
+                res[layer.signalL].bga_min_pitch = all_bga_min_pitch_info["bga_min_pitch"]
+                res[layer.signalL].bga_min_pitch_pad_size = all_bga_min_pitch_info["bga_min_pitch_pad_size"]
+                res[layer.signalL].bga_min_pitch_openging_size = all_bga_min_pitch_info["bga_min_pitch_openging_size"]
+                GEN.deleteLayer({job:job,layer:tmp_layer})
+            } 
+        })
+        GEN.closeStep()
+    })
+    return res
+}
+function min_symbols_anal(props){  // 分析最小symbols
+    var job = props.job
+    var step = props.step
+    var layer = props.layer
+    var symbols = props.symbols
+    var res = {}
+    GEN.selClearFeature()
+    GEN.selectByFilter({include_syms:symbols.symbol})
+    var tmp_layer = layer.signalL + "_tmp_1"
+    selCopyLayer({job:job,layer:tmp_layer})
+    // 分析数据
+    // 尺寸
+    res.min_bga_size = symbols.size
+    // 开窗大小
+    GEN.workLayer({name:layer.solderL,display_number:2,clear_before:'yes'})
+    GEN.selClearFeature()
+    GEN.selRefFeat({layers:tmp_layer,use:'filter',mode:'include'})
+    GEN.selRefFeat({layers:tmp_layer,use:'filter',mode:'cover'})
+    var solderL_tmp = layer.solderL + "_tmp"
+    selCopyLayer({job:job,layer:solderL_tmp})
+    GEN.selClearFeature()
+    GEN.workLayer({name:solderL_tmp,display_number:2,clear_before:"yes"})
+    var symbols_solder = GEN.getLayerSymsHist({job:job,layer:solderL_tmp,step:step})
+    res.min_bga_openging_size = _.values(symbols_solder).reduce(function(a,b){
+        if (b.pad > 0 && b.line) {
+            a.push({symbol:b.symbol, size:Number(b.size)})
+        }
+        return a
+    },[]).sort(function(a,b){return a.size-b.size})[0].size
+    // 间距
+    res.min_bga_pitch = bgaPitch({job:job,step:step,layer:tmp_layer})
 
+    GEN.deleteLayer({job:job,layer:solderL_tmp})
+    GEN.deleteLayer({job:job,layer:tmp_layer})
+    return res
+}
+function all_bga_min_pitch_anal(props){  // 分析所有bga中间距最小的
+    var job = props.job
+    var step = props.step
+    var layer = props.layer
+    var symbols = props.symbols
+    var solder_layer = props.solderLayer
+    var res = {}
+    
+    var ck = "tmp_chk"
+    if(GEN.isChklistExists({job:job,step:step,chklist:ck})){
+        GEN.COM("chklist_delete", { chklist: ck })
+    }
+    // 创建并运行
+    var tmpItem = {
+        name: "bgaPitch",
+        nact: 1,
+        action: "valor_analysis_signal",
+        erf: PAR.erf,
+        params: {   
+            pp_layer: ".affected",
+            pp_spacing: 20,
+            pp_selected: "All",
+            pp_r2c: 10,
+            pp_d2c: 15,
+            pp_sliver: 8,
+            pp_min_pad_overlap: 5,
+            pp_check_missing_pads_for_drills: "Yes",
+            pp_use_compensated_rout: "Skeleton",
+            pp_sm_spacing: "Yes",
+            pp_tests: "Spacing",
+            pp_check_missing_pads_for_drills:"Yes"
+        }
+    }
+    if(PAR.erf){
+        tmpItem.erf = PAR.erf
+    }
+    GEN.createChklist({ // 创建checklist
+        chklist: ck,
+        items: [tmpItem]
+    })
+    GEN.chklistShow({ chklist: ck })
+    GEN.affectedLayer({ affected: "yes", layer: layer, clear_before: "yes" })
+    GEN.chklistRun({
+        chklist: ck,
+        nact: 1,
+        area: 'profile'
+    })
+    
+    var tmp_layer1 = "mk_1_"+layer+"_pitch"
+    var tmp_layer2 = "ms_1_"+layer+"_pitch"
 
+    if(GEN.isLayerExists({job:job,layer:tmp_layer1})){
+        GEN.deleteLayer({job:job,layer:tmp_layer1})
+    }
+    if(GEN.isLayerExists({job:job,layer:tmp_layer2})){
+        GEN.deleteLayer({job:job,layer:tmp_layer2})
+    }
+    GEN.COM("chklist_create_lyrs,chklist="+ck+",severity=3,suffix=pitch");
+    GEN.workLayer({name:tmp_layer2,display_number:1,clear_before:'yes'});
 
+    GEN.selectByFilter({attribute:[{attribute:".string",text:"bga_pitch"}]})
+    var tmp_layer = tmp_layer2 + "_tmp"
+    selCopyLayer({job:job,layer:tmp_layer})
+    GEN.workLayer({name:tmp_layer,display_number:1,clear_before:'yes'});
+    var symbols = GEN.getLayerSymsHist({job:job,layer:tmp_layer,step:step})
+    // 获取最小smd间距
+    var min_symbol = _.values(symbols).sort(function(a,b){return Number(a.size)-Number(b.size)})[0]
+    res.bga_min_pitch = min_symbol.size
+    // 所有BGA中间距最小的PAD大小
+    GEN.selClearFeature()
+    GEN.selectByFilter({include_syms:min_symbol.symbol})
+    var min_pitch_layer = tmp_layer + "_min"
+    selCopyLayer({job:job,layer:min_pitch_layer})
 
+    GEN.workLayer({name:layer,display_number:1,clear_before:'yes'});
+    GEN.selClearFeature()
+    GEN.selRefFeat({layers:min_pitch_layer,use:'filter',mode:'touch'})
+    var min_pad_layer = layer + "_min_pad"
+    selCopyLayer({job:job,layer:min_pad_layer})
+    GEN.workLayer({name:min_pad_layer,display_number:1,clear_before:'yes'});
+    var min_pad_symbols = GEN.getLayerSymsHist({job:job,layer:min_pad_layer,step:step})
+    var min_pad_symbol = _.values(min_pad_symbols).sort(function(a,b){return Number(a.size)-Number(b.size)})[0]
+    res.bga_min_pitch_pad_size = min_pad_symbol.size
 
+    // 最小pitch开窗大小
+    GEN.workLayer({name:solder_layer,display_number:1,clear_before:'yes'});
+    GEN.selClearFeature()
+    GEN.selRefFeat({layers:min_pitch_layer,use:'filter',mode:'touch'})
+    var solder_layer_tmp = solder_layer + "_tmp"
+    selCopyLayer({job:job,layer:solder_layer_tmp})
+    GEN.selClearFeature()
+    GEN.workLayer({name:solder_layer_tmp,display_number:2,clear_before:"yes"})
+    var symbols_solder = GEN.getLayerSymsHist({job:job,layer:solder_layer_tmp,step:step})
+    var symbols_solder_list = _.values(symbols_solder).filter(function(v){return /\d+/ig.test(v.size)})
+    if(symbols_solder_list.length){
+        res.bga_min_pitch_openging_size = symbols_solder_list.sort(function(a,b){return Number(a.size)-Number(b.size)})[0].size
+    }
+    GEN.deleteLayer({job:job,layer:solder_layer_tmp})
+    GEN.deleteLayer({job:job,layer:min_pad_layer})
+    GEN.deleteLayer({job:job,layer:min_pitch_layer})
+    GEN.deleteLayer({job:job,layer:tmp_layer})
+    GEN.deleteLayer({job:job,layer:tmp_layer1})
+    GEN.deleteLayer({job:job,layer:tmp_layer2})
+    return res
+}
+function bgaPitch(props){
+    var job = props.job
+    var step = props.step
+    var layer = props.layer
+    var ck = "tmp_chk"
+    if(GEN.isChklistExists({job:job,step:step,chklist:ck})){
+        GEN.COM("chklist_delete", { chklist: ck })
+    }
+    // 创建并运行
+    var tmpItem = {
+        name: "bgaPitch",
+        nact: 1,
+        action: "valor_analysis_signal",
+        params: {   
+            pp_layer: ".affected",
+            pp_spacing: 20,
+            pp_selected: "All",
+            pp_r2c: 10,
+            pp_d2c: 15,
+            pp_sliver: 8,
+            pp_min_pad_overlap: 5,
+            pp_check_missing_pads_for_drills: "Yes",
+            pp_use_compensated_rout: "Skeleton",
+            pp_sm_spacing: "Yes",
+            pp_tests: "Spacing",
+            pp_check_missing_pads_for_drills:"Yes"
+        }
+    }
+    if(PAR.erf) {
+        tmpItem.erf = PAR.erf
+    }
+    GEN.createChklist({ // 创建checklist
+        chklist: ck,
+        items: [tmpItem]
+    })
+    GEN.chklistShow({ chklist: ck })
+    GEN.affectedLayer({ affected: "yes", layer: layer, clear_before: "yes" })
+    GEN.chklistRun({
+        chklist: ck,
+        nact: 1,
+        area: 'profile'
+    })
+    
+    var tmp_layer1 = "mk_1_"+layer+"_pitch"
+    var tmp_layer2 = "ms_1_"+layer+"_pitch"
 
+    if(GEN.isLayerExists({job:job,layer:tmp_layer1})){
+        GEN.deleteLayer({job:job,layer:tmp_layer1})
+    }
+    if(GEN.isLayerExists({job:job,layer:tmp_layer2})){
+        GEN.deleteLayer({job:job,layer:tmp_layer2})
+    }
+    GEN.COM("chklist_create_lyrs,chklist="+ck+",severity=3,suffix=pitch");
+    GEN.workLayer({name:tmp_layer2,display_number:1,clear_before:'yes'});
+    GEN.selectByFilter({attribute:[{attribute:".string",text:"bga_pitch"}]})
+    var tmp_layer = tmp_layer2 + "_tmp"
+    selCopyLayer({job:job,layer:tmp_layer})
+    GEN.workLayer({name:tmp_layer,display_number:1,clear_before:'yes'});
+    var symbols = GEN.getLayerSymsHist({job:job,layer:tmp_layer,step:step})
+    // 获取最小smd间距
+    var res = _.values(symbols).sort(function(a,b){return Number(a.size)-Number(b.size)})[0].size
+    GEN.deleteLayer({job:job,layer:tmp_layer})
+    GEN.deleteLayer({job:job,layer:tmp_layer1})
+    GEN.deleteLayer({job:job,layer:tmp_layer2})
+    // 矩阵
 
+    return res
+}
 
 function tmp(){
     return {
diff --git a/ats/input/ATS_AIM_data_input.js b/ats/input/ATS_AIM_data_input.js
index 022a654fd334f9f7e4c9b1dc880674ed451ad665..c1a5fbcf626febe323a3e4f87268b1c6ee646ba2 100644
--- a/ats/input/ATS_AIM_data_input.js
+++ b/ats/input/ATS_AIM_data_input.js
@@ -5,21 +5,6 @@ NAME:
 DESCRIPTION: ;
 PARAMETER:
     [
-		{
-			name : 'path',
-			title : '资料路径',
-			type : 'LineEdit',
-			property : {tool_tip : '存放所有料号的文件夹路径,不需要进入到料号文件夹内'},
-		},
-		{
-            name : 'customer',
-			title : '客户配置',
-            type : 'ComboBox',
-            property : {
-				item_list:['customer_1','customer_2','new_data'],
-				tool_tip:'客户代码'
-			}
-		},
 		{
 			name : 'db',
 			title : '料号db',
@@ -86,8 +71,15 @@ if ($.hasOwnProperty('script_parameter')){
 
 try {
 	var par = PAR;
-	if(!par.hasOwnProperty("customer") || par.customer == ""){throw "未填写配置"};
-	if(!par.hasOwnProperty("path") || par.path == ""){throw "未填写路径"};
+	var db_path = db.query("",function(q){
+		return q.selectValue({
+			table:'pub_conf',
+			field:'text_data',
+			where:{path : "quote-data-upload"}
+		})
+	});
+	if(_.isEmpty(db_path)){throw "quote-data-upload error"}
+	par.path = db_path;
 	if(!par.hasOwnProperty("config_path") || par.config_path==""){
 		console.log("========================cfg");
 		par.config_path = "cam/input_data"
@@ -103,6 +95,7 @@ try {
 			where:{id : JobId}
 		})
 	});
+	if(_.isEmpty(db_customer)){throw "customer error"}
 	if(db_customer && !(/^done$/ig.test(db_customer)) && db_customer != "" ){
 		par.customer = db_customer
 	}
@@ -127,7 +120,9 @@ try {
 	custCfg.db = par.db || custCfg.db
 	var step = custCfg.step.toLowerCase()
 	// 获取路径下文件信息
-	var path = par.path || custCfg.path
+	var path = JSON.parse(par.path).path
+	console.log("=============>path:"+ path)
+	if(!fs.exists(path)){throw "path error"}
 	var pathInfo = fs.listDir(path, 1)
 	// 判断存不存在料号文件
 	var jobFile = pathInfo.filter(function(v){return v.baseName.toLowerCase() == job})
diff --git a/ats/rename/ATS_AIM_data_format.js b/ats/rename/ATS_AIM_data_format.js
index 05ea7af405435b043aad9ddc04aca007a7ff793f..fecd2f9f033bcd2ac6fec580b0e68936fd2bfd92 100644
--- a/ats/rename/ATS_AIM_data_format.js
+++ b/ats/rename/ATS_AIM_data_format.js
@@ -3,15 +3,6 @@ NAME:
 DESCRIPTION: ;
 PARAMETER:
     [
-		{
-            name : 'customer',
-			title : '客户配置',
-            type : 'ComboBox',
-            property : {
-				item_list:['customer_1','customer_2','new_data'],
-				tool_tip:'客户代码'
-			}
-        },
         {
 			name : 'config_path',
 			title : '配置地址',
@@ -70,7 +61,6 @@ if ($.hasOwnProperty('script_parameter')){
 try {
     var mode = "use" // develop
     var par = PAR;
-	if(!par.hasOwnProperty("customer") || par.customer == ""){throw "未填写配置"};
 	if(!par.hasOwnProperty("config_path") || par.config_path==""){
 		console.log("========================cfg");
 		par.config_path = "cam/input_data"
@@ -82,6 +72,7 @@ try {
 			where:{id : JobId}
 		})
 	});
+	if(_.isEmpty(db_customer)){throw "customer error"}
 	if(db_customer && !(/^done$/ig.test(db_customer)) && db_customer != "" ){
 		par.customer = db_customer
 	}
@@ -130,21 +121,6 @@ try {
 	if(err){throw err}
 
 
-	// 创建profile
-	var new_martix = GEN.getMatrix({job:job})
-	var profileLayer = Object.keys(new_martix).filter(function(v){
-		return new_martix[v].layer_type=="rout"
-	})
-	if(profileLayer.length){
-		var tmp = profileLayer[0]
-		if(profileLayer.indexOf("outline")>=0){tmp = "outline"}
-		var step = GEN.getStepList({job:job})[0];
-		GEN.openStep({job:job,name:step})
-		GEN.workLayer({name:tmp,display_number:2,clear_before:'yes'})
-		GEN.selCreateProfile()
-		GEN.closeStep()
-	}
-
     // end
     GEN.checkInout({job:job,mode:"out"})  // 结束保存料号 关闭料号
 	GEN.saveJob({ job: job });
@@ -310,6 +286,8 @@ function setDrill(props){   // 设置钻孔
     var signalLayer =matrix.filter(function(v){
         return v.attr.type == "signal" && v.attr.context == "board"
 	})
+	console.log("=================>setdrill:drillLayer:" + _.toString(drillLayer));
+	
 	var layerCount = GEN.getLayerCount({job:job})
     // findSignal 根据传入的数字找到对应的signal层 如 1 => top ; 2 => layer_2 
     function findSignal(num){
@@ -317,7 +295,7 @@ function setDrill(props){   // 设置钻孔
 	}
     function doDrill(drills){  // 分析钻孔层
         return drills.map(function(v){
-            if(v.name == "drill" || v.name=="rout"){
+            if(v.name == "drill" || v.name=="rout" || v.name=="outline"){
                 return {start:findSignal(1), end:findSignal(layerCount), layer:v.name}
             } else {
                 var tmp = /(\d+)-(\d+)/ig.exec(v.tl_name);
diff --git a/config_ats.js b/config_ats.js
index d0548335bed53bc486add79b2e1758944ec93bf1..39f44f92032608a55ccb60f89380a7cc67917ad1 100644
--- a/config_ats.js
+++ b/config_ats.js
@@ -148,8 +148,7 @@
 		}
 	},
 	"customer": {
-		"Customer_1": {
-			"path": "/opt/resource/customer_1",
+		"2171": {
 			"step": "cad",
 			"rules": [
 				{ 
@@ -206,8 +205,7 @@
 				{"orig_name" : ["_isl(\\d+)_bottom"], "tl_name" : "d_($1)-($1+1)"}
 			]
 		},
-		"Customer_2": {
-			"path": "/opt/resource/customer_2",
+		"yucca": {
 			"step": "cad",
 			"rules": [
 				{ 
@@ -346,7 +344,6 @@
 			]
 		},
 		"New_data": {
-			"path": "/opt/resource/new_data",
 			"step": "cad",
 			"rules": [
 				{ 
@@ -450,14 +447,15 @@
 			],
 			"tl_name": [
 				{"orig_name" : ["pasttop.art","^past_top$","top_solderpaste"], "tl_name" : "past_top" },
-				{"orig_name" : ["pleg.art","^silk_top$","top_silkscreen"], "tl_name" : "silk_top" },
-				{"orig_name" : ["soldtop.art","^sm_top$","top_soldermask"], "tl_name" : "sm_top" },
-				{"orig_name" : ["top.art","^top$"], "tl_name" : "top" },
-				{"orig_name" : ["inner_(\\d+)\\.art","layer_(\\d+)"], "tl_name" : "l_($1)"},
-				{"orig_name" : ["bottom.art","^bottom$"], "tl_name" : "bottom" },
-				{"orig_name" : ["soldbotm.art","^sm_botm$","bot_soldermask"], "tl_name" : "sm_botm" },
-				{"orig_name" : ["sleg.art","^silk_bot$","bot_silkscreen"], "tl_name" : "silk_bot" },
+				{"orig_name" : ["^silk_top\\.art$","pleg.art","^silk_top$","top_silkscreen"], "tl_name" : "silk_top" },
+				{"orig_name" : ["_r1\\.phd$","_r1\\.fph$","^smt\\.art$","soldtop.art","^sm_top$","top_soldermask"], "tl_name" : "sm_top" },
+				{"orig_name" : ["^top.art$","^top$"], "tl_name" : "top" },
+				{"orig_name" : ["_l(\\d+)\\.phd$","_l(\\d+)\\.fph$","^in_(\\d+)\\.art$","^l(\\d+)\\.art$","inner_(\\d+)\\.art","layer_(\\d+)"], "tl_name" : "l_($1)"},
+				{"orig_name" : ["^bot.art$","^bottom.art","^bottom$"], "tl_name" : "bottom" },
+				{"orig_name" : ["_r\\d\\.phd$","_r\\d\\.fph$","^smb\\.art$","soldbotm.art","^sm_botm$","bot_soldermask"], "tl_name" : "sm_botm" },
+				{"orig_name" : ["^silk_bottom\\.art$","sleg.art","^silk_bot$","bot_silkscreen"], "tl_name" : "silk_bot" },
 				{"orig_name" : ["pastbotm.art","^past_botm$","bot_solderpaste"], "tl_name" : "past_botm" },
+				{"orig_name" : ["^nc_drill$","^drill$"], "tl_name" : "drill" },
 				{"orig_name" : "multipack.art", "tl_name" : "array" },
 				{"orig_name" : ["\\.rou$","^rout$"], "tl_name" : "rout" },
 				{"orig_name" : ["outline.art","^outline$"], "tl_name" : "outline" },
@@ -465,7 +463,7 @@
 				{"orig_name" : "top-enig", "tl_name" : "top-enig" },
 				{"orig_name" : "bot-enig", "tl_name" : "bot-enig" },
 				{"orig_name" : "fab_page2", "tl_name" : "fab_page2" },
-				{"orig_name" : ["(\\d+)-(\\d+)-laser\\.drl","d(\\d+)-(\\d+)"], "tl_name" : "d_($1)-($2)"}
+				{"orig_name" : ["_d(\\d)(\\d+)\\.drd","_d(\\d)(\\d+)\\.fdr","^d(\\d)(\\d+)\\.art$","(\\d+)-(\\d+)-laser\\.drl","d(\\d+)-(\\d+)"], "tl_name" : "d_($1)-($2)"}
 			]
 		}
 	},
@@ -486,5 +484,5 @@
 		{"tl_name":"array","new_name":"array" ,"attr":{"context":"misc"}},
 		{"tl_name":"fab.art","new_name":"fab.art" ,"attr":{"context":"misc"}}
 	],
-	"delSameJob": "no"
+	"delSameJob": "yes"
 }})()
\ No newline at end of file
diff --git a/test/ATS_AIM_input_data copy.js b/test/ATS_AIM_input_data copy.js
index e071d9f0bf96eb82b20a9e56dc2d1bbdf9f213aa..e6e3793fc895fe8c9a08283591d55d866f31f117 100644
--- a/test/ATS_AIM_input_data copy.js	
+++ b/test/ATS_AIM_input_data copy.js	
@@ -58,7 +58,7 @@ try {
 		job_name: "1",
 		path: "C:/Users/Alan/Desktop/Customer_1"
 	}
-
+	
     var parParams = ["customer", "job_name", "path"]; // par应该有的属性
     var isParExist = parParams.reduce(function (a, b) {
         if (!par.hasOwnProperty(b)) {
diff --git a/test/mytest.js b/test/mytest.js
index ed91ddd6717930058af55d49d5020ae41fb34b60..c30cdc2734c0ce5445cf18fba09b0f2e7d7a88c6 100644
--- a/test/mytest.js
+++ b/test/mytest.js
@@ -8,242 +8,13 @@ var GEN = $.gen;
 var GUI = $.gui;
 var Job = $.job;
 var JobId = $.job_id;
-var drill_toll_manage = {}
 
 try {
-	var job = "sj";
-	if(GEN.isJobExists({job:job})){
-		GEN.closeJob({job:job})
-		GEN.deleteJob({job:job})
-	}
-	var config = {
-        format: {
-            "Gerber274x_1": {
-                "nf1": 5,
-                "nf2": 5,
-                "units": "inch",
-                "zeroes": "leading",
-                "decimal": "no",
-                "nf_comp": 0,
-                "break_sr": "yes",
-                "data_type": "ascii",
-                "separator": "*",
-                "threshold": 200,
-                "drill_only": "no",
-                "multiplier": 1,
-                "resolution": 3,
-                "tool_units": "inch",
-                "coordinates": "absolute",
-                "merge_by_rule": "no",
-                "signed_coords": "no",
-                "text_line_width": 0.0024
-			},
-            "Excellon2_1": {
-                "nf1": 2,
-                "nf2": 3,
-                "units": "inch",
-                "zeroes": "none",
-                "decimal": "no",
-                "nf_comp": 0,
-                "break_sr": "yes",
-                "data_type": "ascii",
-                "separator": "nl",
-                "threshold": 200,
-                "drill_only": "no",
-                "multiplier": 1,
-                "resolution": 3,
-                "tool_units": "inch",
-                "coordinates": "absolute",
-                "merge_by_rule": "no",
-                "signed_coords": "no",
-                "text_line_width": 0.0024
-			}
-        },
-        odb: [{
-            vaild: function(item){
-                return /\.tgz$/ig.test(item.name) // 以.tgz结尾的
-            }
-        }],
-        gerber: [
-            {
-                vaild: function(item){
-                    return /\.art$/ig.test(item.name) // 以.art结尾的
-                },
-                type: "Gerber274x",
-                format: "Gerber274x_1"
-            },
-            {
-                vaild: function(item){
-                    return /\.drl$/ig.test(item.name) // 以.drl结尾的
-                },
-                type: "Excellon2",
-                format: "Excellon2_1"
-            }
-        ]
-	}
-	var path = "C:/Users/Administrator/Desktop/sj(1)"
+    
+    IKM.msg(1)
 
-	var inputInfo = getJobInfo({path:path, job:job,config:config})
-
-	if(/gerber/ig.test(inputInfo.type)){
-        inputInfo.data.forEach(function(file){
-            if(/\.drl$/ig.test(file.name)){
-                var backUpName = file.name+".backup"
-                // 备份
-                fs.copyFile(file.path,file.dir+"/"+backUpName)
-                // 读取
-                var data = fs.readFile(file.path)
-                data = data.split("\n")
-                var head = getHead(data)
-                var body = data
-                // 解析head
-                var headData = head.filter(function(v){
-                    return /Holesize.+Tolerance.+PLATED/ig.test(v)
-                })
-                headData.map(function(v){
-                    var res = {
-                        holesize: {},
-                        tolerance: {},
-                        attr: "",
-                        unit: "",
-                        quantity: 0
-                    }
-                    var holesize_tmp = /(Holesize.+)Tolerance/.exec(v)[1];
-                    holesize_tmp =  holesize_tmp.split("=")
-                    res.holesize.key = holesize_tmp[0].trim()
-                    res.holesize.value = holesize_tmp[1].trim()
-                    var Tolerance_tmp = /(Tolerance.{23})/.exec(v)[1];
-                    Tolerance_tmp = Tolerance_tmp.split("=")[1].split("/")
-                    res.tolerance.top = Tolerance_tmp[0].trim()
-                    res.tolerance.bot = Tolerance_tmp[1].trim()
-                    res.attr = /NON_PLATED/ig.test(v) ? "non_plated" : "plated"
-                    res.unit = /MILS/ig.test(v) ? "inch" : "mm"
-					res.quantity = parseInt(v.split("=").pop())
-					if(!drill_toll_manage.hasOwnProperty(file.name)){
-						drill_toll_manage[file.name] = {}
-					}
-                    drill_toll_manage[file.name][/(\d+)/ig.exec(res.holesize.key)[1]] = res
-                })
-                // 给body添加刀
-				var count = 0;
-				body = body.filter(function(v){
-					return !(/T\d+/ig.test(v))
-				})
-                body.forEach(function(v, i){
-                    if(/^%$|^M00/ig.test(v)){
-                        var k = "T" + getK(++count)
-                        body[i] = v + "\n" + k 
-                    }
-                })
-                // 写入文件
-                var resStr = head.join("\n") + "\n" + body.join("\n")
-                fs.writeFile(file.path,resStr)
-            }
-		})
-		importGerber({job:job,step:"pcs",db:"genesis",data:inputInfo.data}) 
-		// 导入后 修改 tool manager
-		var stepList = GEN.getStepList({job:job})
-		var matrix = GEN.getMatrix({job:job})
-		var drill_layers = Object.keys(matrix).filter(function(v){return matrix[v].layer_type=="drill"})
-		stepList.forEach(function(step){
-			GEN.openStep({job:job,name:step})     
-			drill_layers.forEach(function(layer){
-				var drill_tool_manage_info = drill_toll_manage[layer]
-				var drill_tool_keys = Object.keys(drill_tool_manage_info).sort(function(a,b){return a-b})
-				GEN.COM("tools_tab_reset")
-				drill_tool_keys.forEach(function(key){
-					var val = drill_tool_manage_info[key]
-					GEN.COM("tools_tab_add", {
-						num: key,
-						type: /plated/ig.test(val.attr) ? "plate" : "nplate",
-						min_tol: Number(val.tolerance.top),
-						max_tol: Number(val.tolerance.bot),
-						finish_size: Number(val.holesize.value),
-						drill_size: Number(val.holesize.value)
-					})
-				})
-				GEN.COM("tools_set",{layer:layer,thickness:0,user_params:1,slots:"by_length"})
-			})
-			GEN.closeStep()
-		})
-    }
 	return "Done"
 } catch (e) {
 	IKM.msg(e)
 	return "Error"
 }
-
-function getJobInfo(props){
-    var path = props.path
-    var config = props.config
-    var job = props.job
-    var files = fs.listDir(path)
-    files = files.filter(function(v){return v.isFile})   // 过滤出文件
-    // 先判断是不是odb
-    var odbFiles = files.filter(function(file){   // 拿到odb文件
-        return config.odb.reduce(function(a,b){
-            if(b.vaild(file)){
-                a = true
-            }    
-            return a
-        }, false)
-    })
-    if(odbFiles.length){
-        return {
-            type: "odb",
-            data: odbFiles[0]
-        }
-    }
-    var gerberFiles = files.filter(function(file){   // 拿到odb文件
-        return config.gerber.reduce(function(a,b){
-            if(b.vaild(file)){
-                file.gerber = config.format[b.format];
-                file.type = b.type;
-                a = true
-            }      
-            return a
-        }, false)
-    })
-    if(gerberFiles.length){
-        return {
-            type: "gerber",
-            data: gerberFiles
-        }
-    }
-    return "none"
-}
-
-function importGerber(props){  // job   db  step
-    var job = props.job
-    var step = props.step
-    var files = props.data
-    GEN.createJob({name:job,db:props.db})
-    GEN.createStep({job:job,name:props.step})
-    var gerberInfo = files.map(function(item){
-        var gerberCfg = JSON.parse(JSON.stringify(item.gerber));
-        gerberCfg.layer = item.name.toLowerCase()
-        gerberCfg.path = item.path
-        gerberCfg.format = item.type
-        gerberCfg.job = job
-        gerberCfg.step = step
-        return gerberCfg
-	})
-    GEN.COM("input_manual_reset")
-    gerberInfo.forEach(function(v){
-        GEN.COM("input_manual_set",v)
-    })
-    GEN.COM("input_manual")
-}
-
-function getHead(arr,head){
-	head = head || [];
-	if(arr[0] != "%"){
-		head.push(arr.shift())
-		return getHead(arr,head)
-	} else {
-		return head
-	}
-}
-function getK(count){
-	return count < 10 ? "0" + String(count) : String(count)
-}
\ No newline at end of file
diff --git a/test/test.js b/test/test.js
index faa6f9e4e37c01483785ad87c6a0f776812fc964..785c8422ecb5aa2d9033da3afbe6e792cdd0de8a 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1,5 +1,62 @@
+var func = function (ARGV) {
+    var jobId = ARGV["job_id"];
+    var tableName = "pdm_job_" + ARGV["jobcategory"] + "_layer";
+    //GUI.msgbox({text: TDataParse.variant2JsonStr(tableName)});
+    var db = new TSqlQueryV2(T_SQLCNT_POOL.getSqlDatabase());
+    db.begin();
+    try {
+        var oLayers = db.selectMapMap({
+            table: tableName,
+            field: ["odb_name", "release_status"],
+            where: {
+                job_id: jobId
+            },
+            uniquefield: "odb_name"
+        });
+        if (db.lastError().isValid()) throw db.lastError();
+        //GUI.msgbox({text: TDataParse.variant2JsonStr(oLayers)});
 
+        db.deleteRow({
+            table: tableName,
+            where: {
+                job_id: jobId
+            }
+        });
+        if (db.lastError().isValid()) throw db.lastError();
 
-var str = "-0.0001"
+        var fieldLst = ["name", "odb_context", "odb_type", "odb_polarity", "odb_side", "drl_start", "drl_end",
+            "row_num", "type", "drl_start_num", "drl_end_num", "drl_from_num", "drl_to_num", "drl_connect_to",
+            "odb_name", "side", "stackup_num", "customer_field", "input_file_name", "odb_row_num"
+        ];
 
-console.log(Number(str));
+        for (var i = 0; i < ARGV["layers"].length; i++) {
+            layerName = ARGV["layers"][i];
+            var layerInfo = ARGV["matrix"][layerName];
+            var tmpData = {
+                "job_id": jobId,
+                "name": layerInfo["name"]
+            };
+            if (ARGV["releasestatus"] != undefined && ARGV["releasestatus"] != null && ARGV["releasestatus"].length > 0 &&
+                ARGV["releasestatus"][layerInfo["odb_name"]] != undefined && ARGV["releasestatus"][layerInfo["odb_name"]] != null) {
+                tmpData["release_status"] = ARGV["releasestatus"];
+            } else {
+                tmpData["release_status"] = oLayers.hasOwnProperty(layerInfo["odb_name"]) ? oLayers[layerInfo["odb_name"]]["release_status"] : null;
+            }
+            for (n = 0; n < fieldLst.length; n++) {
+                tmpData[fieldLst[n]] = layerInfo[fieldLst[n]];
+            }
+            //GUI.msgbox({text: TDataParse.variant2JsonStr(tmpData)});
+            db.insertRow({
+                table: tableName,
+                data: tmpData
+            });
+            if (db.lastError().isValid()) throw db.lastError();
+        }
+        db.commit();
+        return new TDataResponse();
+    } catch (err) {
+        print(err.text());
+        db.rollback();
+        return new TDataResponse(err, "");
+    }
+}
\ No newline at end of file