=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:
功能简介
检查原稿最小线宽线距.
参数配置
● CheckList名称
设置CheckList名称.
● Drill Summary CheckList编号
设置Drill Summary CheckList编号.
=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("
",@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('
',@error)."
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});
}