=head
 NAME: TL_READIN_check_org_linewidth_spacing
 DESCRIPTION: 检查钻孔Pad大小.
 PARAMETER:
	{items => [
		{
			name=>'check_list',
			label=>'CheckList名称',
			type=>'string',
			remark=>'CheckList名称',
			must_field=>1,
		},
		{
			name=>'drill_summary_nact',
			label=>'Drill Summary CheckList编号',
			type=>'integer',
			remark=>'Drill Summary CheckList编号',
			must_field=>1,
		},

	]}
	
 VERSION_HISTORY:
	V1.00 2011-05-27 Tony Guo
	   1.新版本
	V1.01 2016-09-26 mast
		添加rill summary分析出错原因
	V1.02 2016-10-18 John
		更新INCAM和Genesis取分析结果错误的不同点。
	V1.03 2017-02-22 Ferre
		Fixed Bug for Same Hole size with Both Via & PTH.		
	V1.04 2018-09-10 Ferre
		Add SymmetricalDrill Check on Laser/Mech Type Define.
		
	V1.05 2019-04-20 mast
	优化 2038
	Echk tool  PE定义drill infos=》 CAM根据PE信息,更改echk料号孔径
	V1.06 2019-05-13 mast
	优化 2051
		在Read in item 33: Update drill info to database

		1,程序判断出有laser drill on or close  mechanical,邮件中带上如下信息,发自动邮件给PE CAM.

		(There is FV2 stack up which is forbidden in SHA plant.)

		2,并推送EQ条目和建议。	

	V1.07 2019-05-20 mast 
	 系统优化:2089
			Checked with Spring 
			Follow the same rule to identy the drill type on QEC stage 
			the old rule : Hole size >=7mil , Type = mechanical hole 
			Hole size <7mil , Type =laser hole 
			
			The Revision: hole size >= 150um ,Type = mechanical hole 
			hole size <150um ,Type = laser hole 

			
	V1.08 2019-09-05 mast
	 系统优化:2293
	 分割孔带中的component_via属性,再上传原稿drill信息时,额外开一条记录,并且在数据库中勾选上laser_on_component
	
		传PE 孔层时,按照ho12层合并到laser层中,如laser2-2,和合并到laser2-3 (4层板)
	V1.09 2020-04-02 john
	优化 2749
	存在非FV3结构,请联系Cassiel/8127设计新版本TCT及Efid coupon!
	V1.09 2020-06-08 john
	优化 2843
	存在FV2结构,暂停,让人工在判断一次!
	
	V1.10 2020-09-25 mast
	优化 3224
	show_form 窗口不输入值的时候可以继续运行
	
	
 HELP:
	<html><body bgcolor="#DDECFE">
	  <font size="3" color="#003DB2"><p>功能简介</p></font>
		<p> 检查原稿最小线宽线距.</p>
		<br>
	  <font size="3" color="#003DB2"><p>参数配置</p></font>
		<font color="#008000"><p> ● CheckList名称</p></font>
		  <p> 设置CheckList名称.</p>
		<font color="#008000"><p> ● Drill Summary CheckList编号</p></font>
		  <p> 设置Drill Summary CheckList编号.</p>
		<br>
		
  </body></html>
  
=cut

#use strict;
#my ($JOB,$GEN,$GUI,$DB,$JOB_ID,$PAR,$APP,$MW);
use utf8;
use Encode;
use Data::Dump 'dump';
my $Return = 'Done';
my $Job = $JOB.'_chk';
my $incam = 'no';
if ($GEN->{GEN_TYPE} =~/incam/i) {
	$incam = 'yes';
}
my $max_drill=150/25.4;
my @selstep;
use_module('Top::MailSender');
my $customer = 	$ARGS{CUSTOMER};
try {
	
	if (!defined $Job or $Job =~ /^\s*$/){
		$GUI->msgbox(-icon=>'error',-text=>'未定义料号名');
		return 'Error';
	}
	my $layercount = $GEN->getLayerCount(job=>$Job);
	my $half_layercount = $layercount/2 + 0.5;
	
	my $arrayhash = $DB->select_arrayhash(-table=>'job_org_layer', -field=>['drl_connect_to','drl_connect_point','tl_name'],-where=>{job_id=>$JOB_ID,type=>'drill'});
	my @fv2_error;
	my @fv2_mail;
	my (@num_count,$Core_mark);
	foreach my $hash (@$arrayhash) {
		if ($hash->{tl_name} =~/^laser/) {
			if ($hash->{drl_connect_to} =~/^(ftdrill\d+\-\d+)$/) {
				if ($hash->{drl_connect_point}> 0){
					push @fv2_error,$hash->{drl_connect_point};
					push @fv2_mail, $hash->{drl_connect_to}.' touch '.$hash->{tl_name}." count $hash->{drl_connect_point}";
				}
			}
			my ($tmp_START,$tmp_END) = $hash->{tl_name} =~/^laser(\d+)\-(\d+)/i;
			if ($tmp_START < $half_layercount and $tmp_END >$half_layercount) {
				$Core_mark = "yes";
			}
			foreach my $tmp($tmp_START..$tmp_END){
				push @num_count,$tmp if (!grep/^$tmp$/,@num_count);
			}
		}
	}
	if ( $customer eq '1352' and ($Core_mark ne "yes" or @num_count != $layercount)) {
		#$GUI->msgbox(-icon=>'info',-text=>"存在非FV3结构,请联系Cassiel/8127设计新版本TCT及Efid coupon!");
		my $ans = $GUI->confirm("存在非FV3结构,请联系Cassiel/8127设计新版本TCT及Efid coupon,是否发送邮件?");
		if ($ans eq "yes") {
			my $username =$GEN->getUserName();
			my $subject = "$Job is not ncn strucutre , please contact with Cassiel design TCT and Efid Coupon";
			my $body = "$Job is not ncn strucutre , please contact with Cassiel design TCT and Efid Coupon";
			Top::MailSender->send_mail(
					subject => $subject,
					#to => 'john.sun@cn.ats.net,cassiel.zhang@cn.ats.net',
					# cc_user=>join(',',Top::MailSender->get_mail_list($PAR->{mail_group},'cc')),
					cc_user=>[$username],
					group => "1352_ncn_inform",
					# to =>'test1',
					body=>[$body],
				);
		}
		
		
		
	}
	if (@fv2_error) {
		my $confirm = $GUI->msgbox(-title=>'Confirm',-text=>"判断是FV2,请确认是否OK。",-buttons=>['No'=>'no','Yes'=>'yes',"查看"=>'close']);

		if ($confirm eq "close") {
			while (1) {
				my $result = $GEN->PAUSE("Check Netlist");
				if ($result eq "OK") {
					$confirm = $GUI->msgbox(-title=>'Confirm',-text=>"判断是FV2,请确认是否OK。",-buttons=>['No'=>'no','Yes'=>'yes',"查看"=>'close']);
					last if ($confirm ne "close");
				}else{
					last;
				}
			}
		}
		
		mail_sand_task(jobname=>$JOB,
								title=>'FV2_mail',
								subject=>"[$JOB]There is FV2 stack up which is forbidden in SHA plant",
								body=>join("<br>",@fv2_mail),
								sand_mode=>'always',
								) if ($confirm eq "yes");
	}
	#
	#@fv2_error='';
	my $check_eq=$DB->get_job_engchk(-jobid=>$JOB_ID,-engchkitemid=>2180);
	#$GUI->debug("@fv2_error");
	#$GUI->debug(dump \$check_eq);
	my $ENUM_ENGCHK_STATUS = $APP->{DB}->get_enum_hash(-category=>'enum_engchk_status');
	my $eq_version = $DB->get_job_engchk_version(-jobid=>$JOB_ID);	
	my ($exist_eq,$check_by_pe);
	my $mark_cam;
	my $item_max_version = $check_eq->{version};
	foreach my $f (@{$check_eq->{problems}}){	
		if ($f->{selected}==1 and $item_max_version == $f->{version}){
			#Replied
			#Check_Finish
			if ($ENUM_ENGCHK_STATUS->{$f->{enum_engchk_status}}{flow_order} >= $ENUM_ENGCHK_STATUS->{'Replied'}{flow_order}){
				$check_by_pe ='yes';
			}
			if ($ENUM_ENGCHK_STATUS->{$f->{enum_engchk_status}}{flow_order} >= $ENUM_ENGCHK_STATUS->{'Check_Finish'}{flow_order} and ($f->{enum_engchk_problem_type} =~/ok/i or $f->{enum_engchk_problem_type} =~/na/i)){
				$check_by_pe ='yes';
			}			
			$exist_eq ='yes';
		}
	}
	my $now = $APP->{DB}->get_now();
	my $log = dump({who=>$APP->{USER_NAME},type=>'info',action=>'System update',date_time=>$now,remark=>'Create EQ'}).',';
	####如果有问题,并且状态在cam这里,将直接删除后更新。
	#$GUI->debug("$check_by_pe");
	if (!$check_by_pe and $fv2_error[0]>0) {
		my $questions;
		$questions->{'question1'}{'value'}={quantity=>join(";",@fv2_error)};		
		if ($exist_eq eq 'yes') {
			if ($GUI->confirm("EQ:[$check_eq->{display_name}]\n已经存在,是否更新?") eq 'yes'){
				foreach my $f (@{$check_eq->{problems}}){
					
					#if ($f->{selected}==1 and ($f->{enum_engchk_problem_type} =~/ok/i or $f->{enum_engchk_problem_type} =~/na/i)){
						save_job_engchk_question(-jobid=>$JOB_ID,-engchkitem=>'EQM_if_laser_drill_on_mechanical_hole',-log=>$log,-questions=>\%$questions,-delete=>'yes',-version=>$check_eq->{version});
						$mark_cam='yes';
						#next;
					#}

					
				}
			}
		}
		else{
			save_job_engchk_question(-jobid=>$JOB_ID,-engchkitem=>'EQM_if_laser_drill_on_mechanical_hole',-log=>$log,-questions=>\%$questions,-delete=>'yes');
		}
	}
	elsif ($check_by_pe eq 'yes'){
#$GUI->debug(dump \@{$check_eq->{problems}});
		foreach my $f (@{$check_eq->{problems}}){
			if (($f->{selected}==1 and ($f->{enum_engchk_problem_type} =~/ok/i or $f->{enum_engchk_problem_type} =~/na/i)) or @fv2_error){
				 #or ($f->{name} eq 'question1' and !$f->{selected})
				my $questions;
				$questions->{'question1'}{'value'}={quantity=>join(";",@fv2_error)};
				if ($ENUM_ENGCHK_STATUS->{$f->{enum_engchk_status}}{display_name}) {
					if ($GUI->confirm("EQ:[$check_eq->{display_name}]\n条目:$f->{display_name}\n并且为[$f->{enum_engchk_problem_type}]项目\n此EQ已经Follow PE EQ状态:[$ENUM_ENGCHK_STATUS->{$f->{enum_engchk_status}}{display_name}]\n是否升级更新?") eq 'yes'){
						if ($eq_version >= $f->{version}){
							my $eq_version1=$eq_version+1;
							save_job_engchk_question(-jobid=>$JOB_ID,-engchkitem=>'EQM_if_laser_drill_on_mechanical_hole',-version=>$eq_version1,-questions=>\%$questions);
							$mark_cam='yes';
						}
					}	
				}
			}

		}		
		
	}
	elsif(!$exist_eq){
		my $ok;
		$ok->{'na'}= 'ok';	
		save_job_engchk_question(-jobid=>$JOB_ID,-engchkitem=>'EQM_if_laser_drill_on_mechanical_hole',-log=>$log,-questions=>\%$ok);	
	}
	if ($mark_cam) {
		$GUI->msgbox(-icon=>'info',-text=>"[$check_eq->{display_name}]有升级或刷新,请到[EQ-3 Drill check]workflow再次检查后follow EQ");
	}
	


	
	#判断料号是否存在;
	unless ($GEN->isJobExists(job=>$Job)){
		$GUI->msgbox(-icon=>'error',-text=>"料号[$Job]不存在!");
		return 'Error';
	}
	$GEN->openJob(job=>$Job);
	
	my @steps = $GEN->getStepList(job=>$Job);
	
	if (@steps != 1){
		@selstep = $GUI->select_step(-title=>'请选择包含钻孔信息的Step',-steplist=>\@steps,-selectmode=>'multiple');
		return 'Cancel' unless @selstep;
	}
	else{
		@selstep = @steps;
	}
	$GEN->openStep(job=>$Job,name=>$selstep[0]);
	my @form_items;
	foreach my $item (@selstep){
		my $tmp = {
			name=>$item,
			label=>$item,
			type=>'enum',
			must_field=>1,
			property=>{
				tl_field=>['name'=>'scalar',display_name=>'text'],
				tl_value_field=>'name',
				tl_data=>[
					{name=>'card',display_name=>'Card'},
					{name=>'array',display_name=>'Array'},
					#{name=>'coupon',display_name=>'Coupon'},
				]
			}
		};
		push @form_items,$tmp;
	}
my $stepinfo = $GUI->show_form(-title=>'请定义Step类型',-items=>\@form_items,-defaultsize=>[300,300],-showcheck => 1,-gen => $GEN,);
	return 'Cancel' unless $stepinfo;
	my $check_list = $PAR->{check_list};
	my $matrix = $GEN->getMatrix(job=>$Job);
	my (@drill_layers,@signal_layers);
	foreach my $item (sort{$a->{row} <=> $b->{row}} values %$matrix){
		if ($item->{context} eq 'board' and $item->{layer_type} eq 'drill'){
			push @drill_layers,$item;
		}
		elsif ($item->{context} eq 'board' and $item->{layer_type} =~ /^(signal|power_ground|mixed)$/){
			push @signal_layers,$item;
		}
	}
	my $num;

	foreach my $drill (@drill_layers){
		$num++;
		$GEN->renameLayer(job=>$Job,layer=>$drill->{name},new_name=>$num.'_drill');
	}

	$matrix = $GEN->getMatrix(job=>$Job);
    foreach my $layer (sort {$matrix->{$a}{row} <=> $matrix->{$b}{row}}  keys %$matrix) {		
        if ($layer =~/comp_\+_top|comp_\+_bot/i ){
            $GEN->COM('delete_comp');
			last;
        }
    }	
	$matrix = $GEN->getMatrix(job=>$Job);
	@drill_layers=();
	@signal_layers=();
	foreach my $item (sort{$a->{row} <=> $b->{row}} values %$matrix){
		if ($item->{context} eq 'board' and $item->{layer_type} eq 'drill'){
			push @drill_layers,$item;
		}
		elsif ($item->{context} eq 'board' and $item->{layer_type} =~ /^(signal|power_ground|mixed)$/){
			push @signal_layers,$item;
		}
	}	
	
	
	### Update check if Drill layer is only 1-2/2-3/... and Symetrical Type , like 1-10,2-9,3-8 ... (10 Layer for example)
	### If YES $isSymmetricalDrill = 1, Else take is 0
	### SymmetricalDrill Means 1-10, 2-9 , should be Mech Hole, Even the hole size is < 7 mil
	my $isSymmetricalDrill = 1;
	foreach my $item (@drill_layers){
		if (abs($item->{drl_start_num} - $item->{drl_end_num}) != 1
			and $item->{drl_start_num} + $item->{drl_end_num} != $layercount + 1) {
			$isSymmetricalDrill = 0;
			last;			
		}
	}
	
	foreach my $item (@drill_layers){
		my $type = check_drill_hole_size($item->{name});
		if ($item->{drl_start_num}<$half_layercount and $item->{drl_end_num} < $half_layercount and $type eq 'laser'){
			$item->{tl_name} = 'laser'.$item->{drl_start_num}.'-'.$item->{drl_end_num};
			$item->{tl_type} = 'laser_drill';
			my @c_drls;
			foreach my $drl (@drill_layers){
				if ($drl->{drl_start_num} == $item->{drl_end_num}){
					push @c_drls,$drl,
				}
			}
			if (@c_drls){
				my @tl_data = ({name=>'',tl_name=>''});
				foreach my $it (@c_drls){
					push @tl_data,{name=>$it->{name},tl_name=>$it->{tl_name}};
				}
				my $tmp = {
					name=>$item->{name},
					label=>$item->{name},
					type=>'enum',
					property=>{
						tl_field=>['name'=>'text',tl_name=>'scalar'],
						tl_value_field=>'tl_name',
						tl_data=>\@tl_data,
					}
				};
			}
		}
		elsif($item->{drl_start_num}>$half_layercount and $item->{drl_end_num} > $half_layercount and $type eq 'laser'){
			$item->{tl_name} = 'laser'.$item->{drl_start_num}.'-'.$item->{drl_end_num};
			$item->{tl_type} = 'laser_drill';
			my @c_drls;
			foreach my $drl (@drill_layers){
				if ($drl->{drl_end_num} == $item->{drl_start_num}){
					push @c_drls,$drl,
				}
			}
			if (@c_drls){
				my @tl_data = ({name=>'',tl_name=>''});
				foreach my $it (@c_drls){
					push @tl_data,{name=>$it->{name},tl_name=>$it->{tl_name}};
				}
				my $tmp = {
					name=>$item->{name},
					label=>$item->{name},
					type=>'enum',
					property=>{
						tl_field=>['name'=>'text',tl_name=>'scalar'],
						tl_value_field=>'tl_name',
						tl_data=>\@tl_data,
					}
				};
			}
		}
		else{
			if ($item->{drl_start_num} == 1 and $item->{drl_end_num} == $layercount){
				if ($isSymmetricalDrill) {
					$item->{tl_name} = 'drill';
					$item->{tl_type} = 'main_drill';
				}else {
					if ($type eq 'laser'){
						$item->{tl_name} = 'laser'.$item->{drl_start_num}.'-'.$item->{drl_end_num};
						$item->{tl_type} = 'laser_drill';
					}
					elsif ($type eq 'mech'){
						$item->{tl_name} = 'drill';
						$item->{tl_type} = 'main_drill';
					}
					else{
						$item->{tl_name} = 'drill';
						$item->{tl_type} = 'main_drill';
					}
				}				
			}
			else{
				if ($isSymmetricalDrill and abs($item->{drl_start_num} - $item->{drl_end_num}) != 1) {
					$item->{tl_name} = 'drill'.$item->{drl_start_num}.'-'.$item->{drl_end_num};
					$item->{tl_type} = 'bury_drill';					
				}else {
					my $singleType = check_hole_size($item->{name});			
					if ($singleType eq 'laser'){
						$item->{tl_name} = 'laser'.$item->{drl_start_num}.'-'.$item->{drl_end_num};
						$item->{tl_type} = 'laser_drill';
					}
					else{
						$item->{tl_name} = 'drill'.$item->{drl_start_num}.'-'.$item->{drl_end_num};
						$item->{tl_type} = 'bury_drill';
					}					
				}
				
			}
		}
	}
 #$GUI->debug(dump \@drill_layers);
	# exit;
	
	$DB->delete(-table=>'job_org_layer_drillinfo',-where=>{job_id=>$JOB_ID});
	foreach my $step (keys %$stepinfo){
		$GEN->openStep(job=>$Job,name=>$step);
		
		return unless ($GEN->PAUSE("Please check the profile which used as check area!"));
		$GEN->openStep(job=>$Job,name=>$step);
		$GEN->units(type=>'inch');
		my @check_list = $GEN->getChecklist(job=>$Job,step=>$step);
		if (! grep(/^\Q$check_list\E$/,@check_list)){
			$GEN->chklistFromLib(chklist=>$check_list);
		}
		$GEN->chklistShow(chklist=>$check_list);
		$GEN->chklistRun(chklist=>$check_list,nact=>$PAR->{drill_summary_nact});
		# return unless ($GEN->PAUSE("FERRE MANUAL Check REPORT!"));
		my @chkresult = $GEN->getCheckMeas(job=>$Job,step=>$step,chklist=>$check_list,nact=>$PAR->{drill_summary_nact});
		my %error;
		if ($incam eq "no") {
			%error = $GEN->INFO(entity_type => 'check',
				entity_path => "$Job/$step/$check_list",
				data_type => 'STATUS',
				options => "action=$PAR->{drill_summary_nact}",
			);	
		}else{
			%error = $GEN->INFO(entity_type => 'check',
				angle_direction=>'ccw',				
				entity_path => "$Job/$step/$check_list",
				data_type => 'STATUS',
				options => "action=$PAR->{drill_summary_nact}",
			);	
		}
		
	
		if ($GEN->{doinfo}{gSTATUS} eq 'ERROR'){
			$GUI->msgbox(-icon=>'error',-text=>"Drill summary分析出错,请检查Surface Analyzer,可能是surface问题造成");
			exit;
		}
		my %pad_size;
		foreach my $item (@chkresult){
			my @tmp = split(/ /,$item);
			next unless ($tmp[0] =~ /_(inner|outer)__(VIA|PTH)_(.*)_AR/);
			my ($drillname) = $tmp[0] =~ /^(.*)_(?:inner|outer)/;
			my $h_size = $tmp[4];
			$h_size =~ s/r//i;
			my $p_size = $tmp[2]*2+$h_size;
			my $sig_layer = $tmp[1];
			my $key = $drillname.':'.$h_size.':'.$sig_layer;
			
			my $exist_size = $pad_size{$key}{min_pad_size};
			## Fixed Bug for Same Hole size with Both Via & PTH, Ferre. 2017-02-22
			if (! $exist_size or $exist_size > $p_size) {
				$pad_size{$key}{drill_name} = $drillname;
				$pad_size{$key}{hole_size} = $h_size;
				$pad_size{$key}{signal_layer} = $sig_layer;
				$pad_size{$key}{min_pad_size} = $p_size;
				$pad_size{$key}{px} = $tmp[6];
				$pad_size{$key}{py} = $tmp[7];
			}
			#unless ($pad_size{$key}{min_pad_size}){				
			#	$pad_size{$key}{drill_name} = $drillname;
			#	$pad_size{$key}{hole_size} = $h_size;
			#	$pad_size{$key}{signal_layer} = $sig_layer;
			#	$pad_size{$key}{min_pad_size} = $p_size;
			#	$pad_size{$key}{px} = $tmp[6];
			#	$pad_size{$key}{py} = $tmp[7];
			#}		
		}
		#$GUI->debug(dump(\%pad_size));
		
	#	return unless ($GEN->PAUSE("FERRE check area!"));
		foreach my $sig_layer (@signal_layers){
			$GEN->workLayer(name=>$sig_layer->{name},clear_before=>'yes');
			foreach my $item (values %pad_size){
				if ($item->{signal_layer} eq $sig_layer->{name}){
					$GEN->selClearFeature();
					$GEN->selectByFilter(feat_types=>'pad',intersect_area=>'yes',area_rect=>{x1=>$item->{px}-0.003,y1=>$item->{py}-0.003,x2=>$item->{px}+0.003,y2=>$item->{py}+0.003});
					my @feats = $GEN->getFeatures(job=>$Job,step=>$step,layer=>$sig_layer->{name},options=>'select');
					my @rpad;
					foreach my $feat (@feats){
						if ($feat->{type} eq 'pad' and $feat->{symbol} =~ /^r(\d+(\.\d+)?)$/){
							my ($s) = $feat->{symbol} =~ /^r(.*)$/;
							push @rpad,$s;
						}
					}
					foreach my $size (sort {$a<=>$b} @rpad) {		
						if (abs ($size - $item->{min_pad_size}) <= 0.002 or $size > $item->{min_pad_size}) { 
							$item->{min_pad_size} = $size;
							last;
						}
					}
				}
			}
		}
		my %drl_tools;	
		my %num_plus;

		foreach my $drl (@drill_layers){
			$GEN->openStep(job=>$Job,name=>$step);
			$GEN->units(type=>'inch');
			
			$GEN->COM('tools_tab_reset');
			$GEN->COM('tools_merge_ex',layer=>$drl->{name},mode=>'merge');
			$GEN->COM('tools_set',layer=>$drl->{name},thickness=>0,user_params=>'',slots=>'by_length');
			
			$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$drl->{name},clear_before=>'yes');
			
			$GEN->selectByFilter(attribute=>['component_via']);
			my $component_via_tmp = $drl->{tl_name}.'_ic_via';
			_deleteLayer(step=>$step,layer=>[$component_via_tmp]);
			if ( $GEN->getSelectCount() > 0 ){
				#$GEN->PAUSE("111111111111111");	
				$GEN->selMoveOther(target_layer=>$component_via_tmp,invert=>'no');
				 $GEN->matrixLayerAttr(job=>$Job,layer=>$component_via_tmp,type=>'drill');
				my $tool_via_tmps = $GEN->getTool(job=>$Job,step=>$step,layer=>$component_via_tmp);
				
				my @drilled_layers;
				foreach my $sig_layer (@signal_layers){
					if ($sig_layer->{tl_num} >= $drl->{drl_start_num} and $sig_layer->{tl_num} <= $drl->{drl_end_num}){
						push @drilled_layers,$sig_layer->{name};
					}
				}
				$num_plus{$drl->{tl_name}} = 0 unless ($num_plus{$drl->{tl_name}});
				my $tmp=0;		
				foreach my $tool (values %$tool_via_tmps){
					if ($tool->{type} ne 'non_plated'){
						foreach my $item (values %pad_size){
							my $sig = $item->{signal_layer};
							if ($item->{drill_name} eq $drl->{name} and
								abs($item->{hole_size} - $tool->{drill_size}) < 0.001)
							{
								$tool->{min_pad_size}{$matrix->{$item->{signal_layer}}{tl_name}} = $item->{min_pad_size};
							}
						}
					}				
					$tmp=$tool->{num} if ($tmp<$tool->{num});
					my $slot=0;
					$slot = $tool->{slot_len} + $tool->{drill_size} if ($tool->{slot_len} !=0);
					
					$DB->insert(-table=>'job_org_layer_drillinfo',
								-data=>{
									job_id => $JOB_ID,
									drill_tl_name => $drl->{tl_name},
									step_type=>$stepinfo->{$step},
									tool_num=>$tool->{num}+$num_plus{$drl->{tl_name}},
									count => $tool->{count},
									shape => $tool->{shape},
									type => $tool->{type},
									drill_size => $tool->{drill_size},
									finish_size => $tool->{finish_size}==0?$tool->{drill_size}:$tool->{finish_size},
									slot_length => $slot,
									min_pad_size => dump($tool->{min_pad_size}),
									max_drill_tol => $tool->{max_tol},
									min_drill_tol => $tool->{min_tol},
									laser_on_component=>'1',
								},
					);
					#$GEN->PAUSE("222222222  $drl->{tl_name}");	
				}
				$num_plus{$drl->{tl_name}}+=$tmp;
				_deleteLayer(step=>$step,layer=>[$component_via_tmp]);
				$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$drl->{name},clear_before=>'yes');
				$GEN->selectByFilter();
				next if ( !$GEN->getSelectCount());				
				
			}
			$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$drl->{name},clear_before=>'yes');

			my $tools = $GEN->getTool(job=>$Job,step=>$step,layer=>$drl->{name});			
			my @drilled_layers;
			foreach my $sig_layer (@signal_layers){
				if ($sig_layer->{tl_num} >= $drl->{drl_start_num} and $sig_layer->{tl_num} <= $drl->{drl_end_num}){
					push @drilled_layers,$sig_layer->{name};
				}
			}
			$num_plus{$drl->{tl_name}} = 0 unless ($num_plus{$drl->{tl_name}});
			my $tmp=0;		
			foreach my $tool (values %$tools){
				if ($tool->{type} ne 'non_plated'){
					foreach my $item (values %pad_size){
						my $sig = $item->{signal_layer};
						if ($item->{drill_name} eq $drl->{name} and
							abs($item->{hole_size} - $tool->{drill_size}) < 0.001)
						{
							$tool->{min_pad_size}{$matrix->{$item->{signal_layer}}{tl_name}} = $item->{min_pad_size};
						}
					}
				}				
				$tmp=$tool->{num} if ($tmp<$tool->{num});
				my $slot=0;
				$slot = $tool->{slot_len} + $tool->{drill_size} if ($tool->{slot_len} !=0);
				
				$DB->insert(-table=>'job_org_layer_drillinfo',
							-data=>{
								job_id => $JOB_ID,
								drill_tl_name => $drl->{tl_name},
								step_type=>$stepinfo->{$step},
								tool_num=>$tool->{num}+$num_plus{$drl->{tl_name}},
								count => $tool->{count},
								shape => $tool->{shape},
								type => $tool->{type},
								drill_size => $tool->{drill_size},
								finish_size => $tool->{finish_size}==0?$tool->{drill_size}:$tool->{finish_size},
								slot_length => $slot,
								min_pad_size => dump($tool->{min_pad_size}),
								max_drill_tol => $tool->{max_tol},
								min_drill_tol => $tool->{min_tol},
							},
				);
				#$GEN->PAUSE("111111111111111");	
			}
			$num_plus{$drl->{tl_name}}+=$tmp;
			

			if ($GEN->isLayerExists(job=>$Job,layer=>$component_via_tmp)){
				$GEN->copyLayer(source_job=>$Job,source_step=>$step,source_layer=>$component_via_tmp,dest_layer=>$drl->{name},mode=>'append');
				_deleteLayer(step=>$step,layer=>[$component_via_tmp]);
			}
			
			
		}
		$GEN->clearLayers();
		$GEN->affectedLayer(mode=>'all',affected=>'no'); 
		#$GEN->closeStep();
	}
	my $jobpath = $GEN->getJobPath(job=>$Job);
	`chmod -R 777 $jobpath` if (-d $jobpath);
	$GEN->closeJob(job=>$Job);
	$GEN->openJob(job=>$Job);
	

	
    my $drill_info = $DB->get_jobinfo(-jobid=>$JOB_ID,
		-jobcategory=>'work',
		-jobinfo=>'pe_check_drill_info',
		#-jobinfo=>'mast1',
		);	
	$drill_info=eval($drill_info);
	
	

	my %drill_info;
	foreach my $ref (@$drill_info){
		push @{$drill_info{$ref->{layer}}},{org_size=>$ref->{org_size},size=>$ref->{size}};
	}
	if (keys %drill_info) {
		my $via_hole_um =500;
		my $v_tmp;
		my $layer_info = $DB->select_arrayhash(
			-table => 'job_org_layer_drillinfo',
			-where => "job_id = $JOB_ID ",
			 -field=>['drill_tl_name','drill_size','type','shape'],

		);
		my %laser;
		foreach my $ref (@$layer_info){
			#next if ($ref->{drill_tl_name} eq 'drill');
			if ($ref->{drill_tl_name} eq 'drill') {
				if ($ref->{type} ne  'non_plated' and	$ref->{shape} ne  'slot'  ) {
					 my $r = $ref->{drill_size}*25.4;	
					push @{$laser{$ref->{drill_tl_name}}},$r  if (!grep /^$r$/,@{$laser{$ref->{drill_tl_name}}});
				}
			}
			elsif ($ref->{drill_tl_name} =~/drill/ ){
				  my $r = $ref->{drill_size}*25.4;	
				   push @{$laser{$ref->{drill_tl_name}}},$r  if (!grep /^$r$/,@{$laser{$ref->{drill_tl_name}}});
			}
			else{
				if ($ref->{drill_tl_name} =~/(\d+)\-(\d+)/) {
					#next if ($max_drill < $ref->{drill_size});
					my $s=$1;
					my $e=$2;
					my $r = $ref->{drill_size}*25.4;	
					if ($e==$s+1){
						push @{$laser{$ref->{drill_tl_name}}},$r if (!grep /^$r$/,@{$laser{$ref->{drill_tl_name}}});
					}
					else{

						for my $n ($s..$e){
							last if ($n == $e);
							my $n1=$n+1;
							my $tl_name ='laser'.$n.'-'.$n1;
							push @{$laser{$tl_name}},$r if (!grep /^$r$/,@{$laser{$tl_name}});
						}
						
					}
				}
				
				
			}
		}			
#$GUI->debug(dump \%laser);
			my %sortdrill;
			foreach my $layer (keys %laser){
				if ($layer eq 'drill'){
					push @{$sortdrill{0}},$layer;
				}
				elsif ($layer=~/(\d+)/) {
					push @{$sortdrill{$1}},$layer;
				}
				
			}
			foreach my $n (sort {$a<=>$b} keys %sortdrill){
				my @layers =@{$sortdrill{$n}};
				foreach my $layer (@layers){
					if ($layer eq 'drill' ){
						foreach my $size (@{$laser{$layer}}) {
							if ($size > $via_hole_um) {
								my $new_size =$size +100;
								$new_size = sprintf("%.0f",$new_size);
								push @$v_tmp,{layer=>$layer,org_size=>$size,color=>'purple',size=>$new_size};
							}
							else{
								push @$v_tmp,{layer=>$layer,org_size=>$size,color=>'blue'};
								
							}
						}							
					}
					elsif ($layer =~/drill/ ){
						foreach my $size (@{$laser{$layer}}) {
							push @$v_tmp,{layer=>$layer,org_size=>$size,color=>'red'};
						}
					}
					else{
						
						foreach my $size (@{$laser{$layer}}) {
							push @$v_tmp,{layer=>$layer,org_size=>$size,color=>'black'};
						}
					}						
				}
			}
			my %get_database_drill;
			foreach my $ref (@$v_tmp){
				push @{$get_database_drill{$ref->{layer}}},{org_size=>$ref->{org_size},size=>$ref->{size}};
			}
			#
			#$GUI->debug(dump \%drill_info);
			#$GUI->debug(dump \%get_database_drill);
			my @error;
			foreach my $tl_name (keys %get_database_drill){
				if (@{$drill_info{$tl_name}}) {
					my @drill1s;
					foreach my $ref (@{$get_database_drill{$tl_name}}){
						push @drill1s,$ref->{org_size};
						
					}
					my @drill2s;
					foreach my $ref1 (@{$drill_info{$tl_name}}){
						push @drill2s,$ref1->{org_size};
					}

				  
					my %seen=();
					foreach (@drill1s){
						$seen{$_}=1;
					}
					my @same=grep($seen{$_},@drill2s);
	
					my @diff=grep(!$seen{$_},@drill2s);
					
					if (@diff) {
						push @error,"$tl_name [@diff]和PE之前load的Drill Org信息不一样";
					}
				}
				else{
					push @error,"原稿孔层[$tl_name]和PE定义的Drill层名对不上";
				}
			}
			#$GUI->msgbox(-icon=>'error',-text=>join("\n",@error));

			if (@error) {
				my $sent_mail = join('<br>',@error)."<br>QEC孔层有更新,请再次检查PE预审信息中drill表";
				mail_sand_task(jobname=>$JOB,
										title=>'pe_eq_info_update_drill',
										subject=>"Pls Update [$JOB] EQM Drill List in PE EQM PRE Info",
										body=>$sent_mail,
										sand_mode=>'always',
										);
				
				
				
				
			}
		
	}


	
	unless ($GEN->{STATUS}){
		return $Return;
	}
	else{
		$GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}}));
		addFlowNotes(-notes=>"   Genesis Error:\n   ".join("\n   ",@{$GEN->{STATUS}}));
		return 'Error';
	}
}
catch Error::Simple with {
	my $error = encode("utf8",shift);
	$GUI->msgbox(-icon=>'error',-text=>$error);
	return 'Error';
}
finally{
	
};

sub check_hole_size{
	my $layer = shift;
	my @steps = $GEN->getStepList(job=>$Job);
	my $drill_type = 'mech';
	foreach my $step (@selstep){
		$GEN->COM('tools_tab_reset');
		$GEN->COM('tools_merge_ex',layer=>$layer,mode=>'merge');
		$GEN->COM('tools_set',layer=>$layer,thickness=>0,user_params=>'',slots=>'by_length');
		my $tools = $GEN->getTool(job=>$Job,step=>$step,layer=>$layer);
		next unless (%$tools);
		foreach my $tool (values %$tools){
			next if ($tool->{drill_size} ==0);
			if ($tool->{drill_size} < $max_drill){
				$drill_type = 'laser';
				last;
			}
		}
		last if $drill_type eq 'mech';
	}
	return $drill_type;
}
sub check_drill_hole_size{
	my $layer = shift;
	my @steps = $GEN->getStepList(job=>$Job);
	my $drill_type;
	foreach my $step (@selstep){
		$GEN->COM('tools_tab_reset');
		$GEN->COM('tools_set',layer=>$layer,thickness=>0,user_params=>'',slots=>'by_length');
		my $tools = $GEN->getTool(job=>$Job,step=>$step,layer=>$layer);
		next unless (%$tools);
		foreach my $tool (values %$tools){
			next if ($tool->{drill_size} ==0);
			if ($tool->{drill_size} < $max_drill and $drill_type !~/laser/){
				$drill_type.= 'laser';
			}
			elsif ($tool->{drill_size} >= $max_drill and $drill_type !~/mech/){
				$drill_type.='mech';
			}
		}
	}
	return $drill_type;
}
sub mail_sand_task {
	my %par = @_; ## subject ##body ## title
	my $mailinfo=$DB->select_hash(-table=>'ats_mail_sand_task',-where=>{mail_title=>$par{title}});
	if ($mailinfo->{status} eq 'Start'){
		my $mail_to=$mailinfo->{mail_to};
		my $mail_cc=$mailinfo->{mail_cc};
		if ($mail_to=~/^sub/){
			$mail_to=eval($mail_to);
			$mail_to= $mail_to->(job_id=>$job_id);
		}		
		else{
			$mail_to=eval($mail_to) if ($mail_to=~/^\$/);
		}
		
		if ($mail_cc=~/^sub/){
			$mail_cc=eval($mail_cc);
			$mail_cc= $mail_cc->(job_id=>$job_id);
		}		
		else{
			$mail_cc=eval($mail_cc) if ($mail_cc=~/^\$/);
		}

		my @to = split(/\;|\:|\,|\n/,$mail_to);
		foreach my $it (@to){
			$it =~ s/(^\s+|\s+$)//g;
		}
		$par{-to} = \@to;
		#$data{cc} =~ s/\s+//g;
		my @cc = split(/\;|\:|\,|\n/,$mail_cc);
		foreach my $it (@cc){
			$it =~ s/(^\s+|\s+$)//g;
		}
		$par{-cc} = \@cc;
		$par{cc_user}='';
		$par{group}='';
		


		#$GUI->debug("@to  m @cc ");
		
		my $subject=$par{subject};
		my $body = $par{body};
			
		my $mail_version = $DB->select_value(
			-table=>'ats_auto_mail_record',
			-field=>'max(mail_version)',
			-where=>"job_id = $JOB_ID and mail_title = '$par{title}'",		
		);
		$mail_version = 0 unless ($mail_version);
		$mail_version++;
		my $resart_mail= 'yes';
		if ($mail_version > 1 and $par{sand_mode} ne 'always' ){
			my $tmp_v=$mail_version-1;
			my $mail_subject = $DB->select_value(
				-table=>'ats_auto_mail_record',
				-field=>'mail_subject',
				-where=>"job_id = $JOB_ID and mail_title = '$par{title}' and mail_version = $tmp_v",
			);
			my $mail_body = $DB->select_value(
				-table=>'ats_auto_mail_record',
				-field=>'mail_content',
				-where=>"job_id = $JOB_ID and mail_title = '$par{title}' and mail_version = $tmp_v",
			);
			if ($mail_subject eq $subject){
				$resart_mail='no';
				if ($mail_body ne $body){
					$resart_mail='yes';
				}				
			}
			elsif ($mail_body ne $body){
				$resart_mail='yes';
			}		

		}
		#$GUI->debug(dump\%par);
		#exit;
		if ($resart_mail eq 'yes'){
			Top::MailSender->send_mail(%par);
			my ($content,$att);
			if (ref $par{body} eq 'ARRAY') {
				($content,$att) =  @{$par{body}};	
			}
			else {
				$content = $par{body};		
			}
			if ($att) {
				my @att = @{$att};
				if (@att) {
					$att = join(',',@att);
					$att = '' unless ($att);		
				}else {
					$att = '';
				}
			}
			else {
				$att = '';
			}

			
			$DB->insert(
				-table=>'ats_auto_mail_record',
				-data=>{
					job_id => $JOB_ID,
					mail_from=>$APP->{USER_NAME},
					mail_to=>$mail_to,
					mail_cc=>$mail_cc,
					mail_subject=>$par{subject},
					mail_title=>$par{title},
					mail_content=>$content,	
					mail_attachment=>$att,
					mail_version=>$mail_version,
				}
			);				
		}
	}
}


sub save_job_engchk_question{
	my %par = @_;
	$par{-version} = $DB->get_job_engchk_version(-jobid=>$par{-jobid}) unless $par{-version};
	my $chkitem_id = $DB->select_value(-table=>'engchk_chkitem',-field=>'id',-where=>{name=>$par{-engchkitem}});
	return unless $chkitem_id;
	my $prob_ids = $DB->select_fieldarray(-table=>'engchk_problem',-field=>'id',-where=>{engchk_chkitem_id=>$chkitem_id});
	my $prob_hash = $DB->select_hashhash(-table=>'engchk_problem',-field=>'*',-hashkey=>'name',-where=>{engchk_chkitem_id=>$chkitem_id});
	my $err;
	my $now = $DB->get_now();
	$DB->begin();
	$DB->delete(-table=>'job_engchk',-where=>{job_id=>$par{-jobid},version=>$par{-version},engchk_problem_id=>$prob_ids}) if ($par{-delete});
	foreach my $prob_name (keys %{$par{-questions}}){
		#$GUI->debug("$prob_name");
		my $tmp = {
			job_id=>$par{-jobid},
			engchk_problem_id=>$prob_hash->{$prob_name}{id},
			version=>$par{-version},
			enum_engchk_status=>$par{-questions}->{$prob_name}{enum_engchk_status}||'New',
			enum_engchk_problem_type=>$prob_hash->{$prob_name}{enum_engchk_problem_type},
			enum_engchk_affected_tooling =>$prob_hash->{$prob_name}{enum_engchk_affected_tooling},
			enum_engchk_problem_report_to =>$prob_hash->{$prob_name}{enum_engchk_problem_report_to},
			log=>$par{-log},
		};
		$par{-questions}->{$prob_name}{text} = $prob_hash->{$prob_name}{problem_detail} unless defined $par{-questions}->{$prob_name}{text};
		$par{-questions}->{$prob_name}{language} = $prob_hash->{$prob_name}{enum_display_name_language} unless defined $par{-questions}->{$prob_name}{language};
		$par{-questions}->{$prob_name}{editable} = $prob_hash->{$prob_name}{editable} unless defined $par{-questions}->{$prob_name}{editable};
		#$tmp->{question} = dump($par{-questions}->{$prob_name});
		$tmp->{question_text} = (defined $par{-questions}->{$prob_name}{text})?$par{-questions}->{$prob_name}{text}:$prob_hash->{$prob_name}{problem_detail};
		$tmp->{question_value} = $par{-questions}->{$prob_name}{value}?dump($par{-questions}->{$prob_name}{value}):undef;
		$tmp->{question_attachment} = $par{-questions}->{$prob_name}{attachment}?dump($par{-questions}->{$prob_name}{attachment}):undef;
		$tmp->{question_user} = $par{-questions}->{$prob_name}{user} || $APP->{USER_FULL_NAME};
		$tmp->{question_timestamp} = $par{-questions}->{$prob_name}{timestamp} || $now;
		#$GUI->debug(dump \$tmp);
		$DB->update_with_insert(-table=>'job_engchk',-data=>$tmp,-where=>['job_id','engchk_problem_id','version']);
		
		#save_job_engchk_question
		$err = $DB->err;
		last if $err;
	}
	if ($err){
		$DB->rollback;
		return $err;
	}
	else{
		$DB->commit;
		return 0;
	}
}

sub _deleteLayer{
    my %par = @_;
    foreach my $layer(@{$par{layer}}){
        $GEN->deleteLayer(layer=>$layer) if ($GEN->isLayerExists(job=>$Job,layer=>$layer));
    }
	$GEN->openStep(job=>$Job,name=>$par{step}) if ($par{step});
}