#! /usr/bin/perl # for Mac OS X (sjis) by Makoto Hiroshige 2003.01.04 # # chkid.pl の出力結果である、整理済み会費納入ファイル checked_record.txt を読み、 # 会費納入状況ファイル bookfile.txt を更新する。新ファイル名 bookfile.txt.new # 同時に、免除対象者のチェック、夫婦会員の納入状況の整合性のチェックも行い、 # 新規免除対象者、夫婦納入状況不整合者は修正する。 # 作業内容のレポートを履歴ファイル logfile.txt に出力する。新ファイル名 logfile.txt.new # # 必要ファイル: checked_record.txt, bookfile.txt, logfile.txt, ID.db # # デフォルトではチェックモードで動作し、 # チェック用のログを mod_book_check.txt に出力する。bookfile.txt と logfile.txt は更新しない。 # mod_book.pl -mod で本書き込みモードで動作し、 # bookfile.txt.new と logfile.txt.new を作成する。 # このときは mod_book_check.txt は出力しない。 # # 支払済年度が 2002 未満から 2002 以上に # 変化した場合、履歴行の最後に「名簿送付」の文字を加える。 # (2003 年と 2004 年 (次回名簿印刷予定年) のみ有効とすること[無効化は手動]) $meibo_send_check = 1; # 2002 年度分に達した場合「名簿送付」を履歴に加えるか sub backup_file { # 使われていないようだ 2003.01.04 $file_name = $_[0]; $backup2 = "$file_name.2"; $backup1 = "$file_name.1"; $backup0 = "$file_name.0"; if( -e $file_name ) { if( -e $backup2 ) { unlink( $backup2 ); } if( -e $backup1 ) { rename( $backup1, $backup2 ); } if( -e $backup0 ) { rename( $backup0, $backup1 ); } rename( $file_name, $backup0 ); } else { die "Can't find $file_name.\n"; } $backup0; } $debug = 1; # default is debug mode. # -mod スイッチが指定されたときは本書き込みモードとして動作する。それ以外はチェックモード。 if( $ARGV[0] eq "-mod" ) { $debug = 0; } else { $debug = 1; } # 出力ファイル名 $bookfile_name = "bookfile.txt.new"; $logfile_name = "logfile.txt.new"; # 入力ファイル名 $bookfile_backup0 = "bookfile.txt"; $logfile_backup0 = "logfile.txt"; $newlog_str = ""; $debug_str = ""; # 「今年」を取得。このスクリプトが起動された時刻から計算。 ($this_day, $this_month, $this_year) = (localtime(time))[3..5] ; $this_year += 1900; $this_month += 1; # 「今日」の日付 $thisday_str = "$this_year年$this_month月$this_day日"; $debug_str .= "《チェック出力 by mod_book.pl 》\t$thisday_str\n\n"; # 免除しきい値年度を計算     ★免除基準はここ★ $exempt_year = $this_year - 45; # 会員番号ファイル ID.db の読み込み open( IDFILE, "ID.db" ) || die "Can't open file \"ID.db\".\n"; while() { chop; ($id,$name,$furigana,$spouse) = split(/\t/); $name =~ s/ +//g; # delete 1byte space $name =~ s/(\x81\x40)+//g; # delete 2bytes space sjis $furigana =~ s/ +//g; # delete 1byte space $furigana =~ s/(\x81\x40)+//g; # delete 2bytes space sjis $idname{$id} = $name; # 会員番号から名前を得るハッシュ $idspouse{$id} = $spouse; # 会員番号から配偶者会員番号を得るハッシュ } close(IDFILE); # 会費納入状況ファイル bookfile.txt の読み込み #  読み込みながら免除該当者のチェックをし、新たに免除になる人にはここで「免」を代入 open( BOOKFILE, $bookfile_backup0 ) || die "Can't open file \"$bookfile_backup0\".\n"; $debug_str .= "■ 新規免除該当者 ■\n\n"; while() { chop; ($id,$paid_year) = split(/\t/); $idset{$id} = $paid_year; # 免除該当者チェック if ( $id =~ /(\d{4})([GE])\d{3}/ ) { if ( $2 eq "G" ) { # 卒業年次 if ( $1 <= $exempt_year ) { # 免除 if( $paid_year ne "免" ) { # まだ免除になっていない→新規免除該当者 $newlog_str_oneline = "$thisday_str\t$id\t$idname{$id}\t新規免除該当者\t$paid_year→免\n"; $newlog_str .= $newlog_str_oneline; $debug_str .= $newlog_str_oneline; $idset{$id} = "免"; } # すでに免除の人はそのまま } # 免除でない→年度の数字の人はそのまま。免除になってしまっている人もそのまま } else { # $2 eq "E" 入団年次 if ( $1 + 4 <= $exempt_year ) { # 免除 if( $paid_year ne "免" ) { # まだ免除になっていない→新規免除該当者 $newlog_str_oneline = "$thisday_str\t$id\t$idname{$id}\t新規免除該当者\t$paid_year→免\n"; $newlog_str .= $newlog_str_oneline; $debug_str .= $newlog_str_oneline; $idset{$id} = "免"; } # すでに免除の人はそのまま } # 免除でない→年度の数字の人はそのまま。免除になってしまっている人もそのまま } } else { # 会員番号のフォーマットが変 die "ID error in file \"$bookfile_backup0\". ID: $id\n"; } } close(BOOKFILE); $debug_str .= "\n"; $debug_str .= "■ 夫婦会員調整 ■\n\n"; # 夫婦会員の夫婦が同じ納入済年度の値であるかどうかチェック #  同じでなければ、大きい方に合わせて、同じにする。 # どちらかが免除であれば、配偶者も免除にする。 foreach (keys %idset) { # print OUTBOOK "$_\t$idset{$_}\n"; $newlog_str_oneline = ""; if ( $idspouse{$_} ne "" ) { $spouse_id = $idspouse{$_}; $self_paid_year = $idset{$_}; $spouse_paid_year = $idset{ $spouse_id }; if ( ($self_paid_year eq "免") && ($spouse_paid_year eq "免") ) { # Do nothing } elsif ( ($self_paid_year eq "免") && ($spouse_paid_year ne "免") ) { $idset{ $spouse_id } = $self_paid_year; $newlog_str_oneline = "$thisday_str\t$spouse_id\t$idname{$spouse_id }\t夫婦会員につき配偶者に揃えて免除とする $spouse_paid_year→$idset{ $spouse_id } (配偶者: $_ $idname{$_} $self_paid_year )\n"; } elsif ( ($self_paid_year ne "免") && ($spouse_paid_year eq "免") ) { $idset{ $_ } = $spouse_paid_year; $newlog_str_oneline = "$thisday_str\t$_\t$idname{$_}\t夫婦会員につき配偶者に揃えて免除とする $self_paid_year→$idset{ $_ } (配偶者: $spouse_id $idname{$spouse_id} $spouse_paid_year )\n"; } elsif ( $self_paid_year > $spouse_paid_year ) { $idset{ $spouse_id } = $self_paid_year; $newlog_str_oneline = "$thisday_str\t$spouse_id\t$idname{$spouse_id }\t夫婦会員につき配偶者のより大きい値に揃えた $spouse_paid_year→$idset{ $spouse_id } (配偶者: $_ $idname{$_} $self_paid_year )\n"; } elsif ( $self_paid_year < $spouse_paid_year ) { $idset{ $_ } = $spouse_paid_year; $newlog_str_oneline = "$thisday_str\t$_\t$idname{$_}\t夫婦会員につき配偶者のより大きい値に揃えた $self_paid_year→$idset{ $_ } (配偶者: $spouse_id $idname{$spouse_id} $spouse_paid_year )\n"; } else { # $self_paid_year == $spouse_paid_year # Do nothing } $newlog_str .= $newlog_str_oneline; $debug_str .= $newlog_str_oneline; } } $debug_str .= "\n"; $debug_str .= "■ 今回の納入 ■\n\n"; # 旧履歴ファイルの全内容を新履歴ファイルにコピー if( !$debug ) { # 本書き込みモードの場合 open( OLDLOG, $logfile_backup0 ); open( NEWLOG, ">$logfile_name" ); # 旧履歴ファイルの全行を新履歴ファイルにそのまま出力 while() { print NEWLOG; } # 旧履歴ファイルは閉じる。新履歴ファイルはこれから行を追加するので閉じない。 close OLDLOG; } # 整理済み会費納入ファイル checked_record.txt を1行ずつ処理 open( IN, "checked_record.txt" ) || die "Can't open file \"checked_record.txt\".\n"; $err_flag = 0; while() { # 整理済み会費納入ファイル1行分の処理はじめ chop; next if /^#/; # skip Comment Line next if /^$/; # skip Empty Line ($date,$id,$name,$paid,$paidy,$method,$rem) = split; # 当該会員番号から支払済年度を取り出し $paid_year に代入。 # $paid_year は西暦年度を表す数字か、「免」という文字 $paid_year = $idset{$id}; # 「今回何年分払ったか」を表す $paidy が 0 なのはナンセンス die "It's nonsence that \$paidy = $paidy.\n" if $paidy == 0; if ( $paid_year eq "免" ) { # 免除会員の処理 (この段階では新規免除該当者にも既に「免」が入れてある) #  ここに該当するのは、免除なのに払ってしまった人 #  支払済年度は「免」なので計算はせずそのままにする。 # 新履歴ファイルに出力するための文字列を作成 $newlog_a_line = "$date\t$id\t$name\t$paid\t$paidy 年分\t$method\t会費免除につき納入済年度は計算しない\t$rem\n"; $newlog_str .= $newlog_a_line; $debug_str .= $newlog_a_line; } else { # 免除会員でない会員の処理 (夫婦会員の片方である場合を含む) $paid_year_before = $paid_year; $what_year_str = ""; for( $i=1; $i<$paidy; $i++ ) { $str = $paid_year_before+$i; $what_year_str .= "$str 年度分, "; } $str = $paid_year_before+$paidy; $what_year_str .= "$str 年度分"; # 支払済年度の値を加算してハッシュに格納 $paid_year += $paidy; $idset{$id} = $paid_year; # 名簿送付チェック if ( $meibo_send_check ) { if ( ($paid_year_before < 2002) && ($paid_year >= 2002) ) { $rem .= " 名簿送付"; } } # 新履歴ファイルに出力するための文字列を作成 $newlog_a_line = "$date\t$id\t$name\t$paid\t$paidy 年分\t$method\t$what_year_str\t$rem\n"; # 新履歴ファイルに出力するための文字列を出力用バッファに加える $newlog_str .= $newlog_a_line; # チェックモード用の出力文字列作成 $debug_str .= "$date $id $name: $paid_year_before 年度まで済: $paidy 年度分納入: $paid_year 年度まで済\n"; $debug_str .= $newlog_a_line; $debug_str .= "$id : $idset{$id}\n"; # 夫婦会員の処理 (この段階では夫婦の納入年度の値は一致している) if ( $idspouse{$id} ne "" ) { $spouse_id = $idspouse{$id}; $paid_year_before = $idset{$spouse_id}; $idset{$spouse_id} = $paid_year; # 新履歴ファイル&チェックファイルに出力する文字列 $newlog_a_line = "$date\t$spouse_id\t$idname{$spouse_id}\t夫婦会員につき配偶者に同期させた: $paid_year_before 年度まで済 → $paid_year 年度まで済 (配偶者: $id $name)\n"; $newlog_str .= $newlog_a_line; $debug_str .= $newlog_a_line; } } # 免除会員でない会員の処理おわり $debug_str .= "\n"; } # 整理済み会費納入ファイル1行分の処理おわり close IN; $debug_str .= "本書き込みは mod_book.pl -mod で行われる。\n"; if( $debug ) { # チェックモードの場合 open( OUTDBG, ">mod_book_check.txt" ) || die "Can't create file \"mod_book_check.txt\".\n"; print OUTDBG $debug_str; close OUTDBG; } else { # 本書き込みモードの場合 # 出力用バッファの内容を新履歴ファイルに追加出力する。 print NEWLOG $newlog_str; close NEWLOG; # ハッシュの内容を新しい会費納入状況ファイルに出力する。 # (出力順はランダム) open( OUTBOOK, ">$bookfile_name" ) || die "Can't create file \"$bookfile_name\".\n"; foreach (keys %idset) { print OUTBOOK "$_\t$idset{$_}\n"; } close OUTBOOK; }