先日より、バーコードレジに切り替えたいな!という事で、SHARPのXE-A407というレジを使い始めました。謳い文句が「SDカードで売上データが吸える」という事なんですが、微妙に活用するための道具が揃っていない感じなので、あれこれしました。データ的にはXE-A417と同じようなので、そちらをお使いの方も居るかもしれません。
http://www.sharp.co.jp/products/xea417/index.html
このレジにしたのは、レジ会社でデータが電子的に取りだせてバーコードが扱えて、という条件で探したら、電子データはレジ会社で全部吸って、データを手元に落として使うには毎月利用料を取る所とかあって、シンプルな使い方が出来そうな所が大手さんに無かったり、あとは高かったりなどが理由です。
事前準備の中で
レジの店舗ロゴ画像なんかは指定の比率で画像を書いてIllustratorから画像出力すれば何とかなります。
それよりも最初に困るのはバーコード登録。バーコードのデータと料金の表が手元にあるのに、パソコン側のサポートソフトでもひとつひとつ手打ちで登録する事になるので、これは困ったという事でデータを眺めて、それっぽい物を出せるようにしました。データのcsv(コード・商品名(全角8文字、半角16文字以内)・所属部門・単価がカンマ区切り)を処理してXMLを吐くものです。レジに渡すデータはUTF-8のXMLですので、csvもUTF-8で書きます。UTF-8のcsvを編集するのには、Excelよりもcsv編集ソフトの方が数段便利*1なので、いろいろ探したところ、UTF-8が扱えて並の機能な物という事でKutoCsvEditorを使っています。登録項目数と商品名16バイト以内の条件が破綻すると編集ソフトでもエラーが出るので要注意です。(スクリプト側でつまもうとしましたが面倒になってやめました。)
#!/usr/bin/perl ## filename ## $datafile="./jancode.csv"; $outfile="./PLU-JAN.xml"; ## get line numbers except header. ## open(FILE, $datafile) or die; # print <FILE>; # output data 1 for <FILE>; # not output data # print $. . 'lines \n'; $lineno= $. ; close(FILE); $lineno= $lineno-1 ; open (IN, $datafile) or die "$!"; open (OUT,"> ".$outfile); ## output headers ## print OUT "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; print OUT "<FILE FILE_NO=\"0x11\" FILE_NAME=\"PLU\" MAX_BLOCK_NUM=\"1\" MAX_RECORD_NUM=\"".$lineno."\" VERSION=\"A407J\">\n"; print OUT " <BLOCK BLOCK_NO=\"1\">\n"; ## main routine ## while (<IN>) { chomp ($_); @data = split(/,/, $_); ## skip first line of data ## next if ($. eq 1); # # 全角、半角空白の除去 # for ($i=0; $i<4; $i++) { # print $data[$i]; # } # print OUT "\n"; $productname = $data[1]; print OUT " <RECORD PLU_CODE=\"100".$data[0]."\">\n"; print OUT " <FIELD FIELD_NO=\"1\" CONTENTS=\"Preset\">\n"; print OUT " <DEPARTMENT>".$data[2]."</DEPARTMENT>\n"; print OUT " <PROGRAM>\n"; print OUT " <AUTO_DELETE>No</AUTO_DELETE>\n"; print OUT " <ENTRY_TYPE>Preset</ENTRY_TYPE>\n"; print OUT " </PROGRAM>\n"; print OUT " <MENU_TYPE>\n"; print OUT " <MENU_TYPE>Normal</MENU_TYPE>\n"; print OUT " </MENU_TYPE>\n"; print OUT " <LNKSET_TABLE_NO>0</LNKSET_TABLE_NO>\n"; print OUT " <PLU_GROUP_NO>0</PLU_GROUP_NO>\n"; print OUT " <MIXMATCH_TABLE>0</MIXMATCH_TABLE>\n"; print OUT " </FIELD>\n"; print OUT " <FIELD FIELD_NO=\"3\" CONTENTS=\"PLU Price\">\n"; print OUT " <PRICE>".$data[3]."</PRICE>\n"; print OUT " </FIELD>\n"; print OUT " <FIELD FIELD_NO=\"4\" CONTENTS=\"PLU Text\">\n"; print OUT " <TEXT>".$productname."</TEXT>\n"; print OUT " </FIELD>\n"; print OUT " </RECORD>\n"; } ## output footers ## print OUT " </BLOCK>\n"; print OUT "</FILE>\n"; close (IN); close (OUT);
日々のデータ
毎日集計しているので電子ジャーナルが1日ごとに切れてしまうのをくっつけたり、などという道具も作りましたが割愛します。
売り上げの集計表がとりあえず出て来るのでそれに依拠しても良いのですが、(電子)ジャーナルと突合せをするのにジャーナルの情報整理と金の集計ぐらいを出してくれると、何かと有り難いな*2と思って、最低限の集計と、電子ジャーナルの余計な情報を削って可読性を上げるスクリプトも書きました。集計したい電子ジャーナル(1ファイル)を指定すると、ごみを掃除した上で小計と現金と信用の集計をざっとしてくれます。ただし、小計が2重になるところなどがあるので額がずれる場合があって(値引きで小計が2回出て来るなど)、そこは個別に探してください。ヒントになる数字(差額や小計の回数など)は集計に出て来ます。
#!/usr/bin/perl # SHARP XE-A407/417 電子ジャーナル処理スクリプト(まとまった電子ジャーナルを指定する) # # 引数にどの電子ジャーナルを使うか指定 # 第1引数にファイル名を指定 $datafile=$ARGV[0]; # $outfile= ## filename ## # $datafile="../SDbackup/".$datadir."/SHARP/ECRXXX13/REDISTER/EJ/".$dataname."/EJFILE.TXT"; # $outfile="../SDbackup/".$dataname.".txt"; # 指定ファイル確認用 # print $datafile; ## get line numbers except header. ## open(FILE, $datafile) or die; # print <FILE>; # output data 1 for <FILE>; # not output data # print $. . 'lines \n'; $lineno= $. ; close(FILE); # $lineno= $lineno-1 ; #小計数カウント初期化 my $subcount = 0; my $creditcount = 0; my $cashcount = 0; open (IN, $datafile) or die "$!"; # open (OUT,"> ".$outfile); $/ = " \n"; while(<IN>) { s/\s{30}\n//; @data = split(/\n/, $_); #中止した履歴についてはそのブロックの処理自体をスキップ #(小計計の狂いをなくすため) if (/中止・・・/) { next; } #比較対照用の生出力 # print $_; # print " ||\n"; foreach my $oneline(@data){ # print "$oneline *\n"; chomp($oneline); #日計、期間計、設定、SDカード関連については集計スキップ if ($oneline =~ /日計/ or $oneline =~ /期間/ or $oneline =~ /点検/ or $oneline =~ /精算/ or $oneline =~ /設定/ or $oneline =~ /SDカ/ ) { last; } #行処理条件 if ($oneline =~ /^(201\d年(.*))(責任\d+)$/) { $yeardate = $2; $yeardate =~ s/\s//g; print "$yeardate"; } elsif ($oneline =~ /^\d+(\#\d{4})\s+$/) { $logno = $1; print " $logno\n"; } elsif ($oneline =~ /^\*\*小計\s+\\(.*)$/) { # 小計でマッチした数をカウントしておく $subcount++; $sum = $1; $sum =~ s/\s//g; print " *小計 $sum\n"; $sum =~ s/,//g; $sum = $sum+0; $subtotal = $subtotal + $sum; } elsif ($oneline =~ /^\(内税\)\s+\\(.*)$/) { #何の処理も出力もしない } elsif ($oneline =~ /^個数\s+(\d*)個$/) { #何の処理も出力もしない # print $1."\n"; } elsif ($oneline =~ /^\*\*合計\s+\\\s(.*)$/) { $ssum = $1; $ssum =~ s/\s//g; print " *合計 $ssum\n"; $ssum =~ s/,//g; $ssum = $ssum+0; $cashtotal = $cashtotal + $ssum; } elsif ($oneline =~ /^現金\s+\\(.*)$/) { # 合計でマッチした数をカウントしておく $cashcount++; $gen = $1; $gen =~ s/\s//g; print " =現金 $gen\n"; $gen =~ s/,//g; $gen = $gen+0; $gentotal = $gentotal + $gen; } elsif ($oneline =~ /^おつり\s+\\(.*)$/) { $tsuri = $1; print " =おつり $tsuri\n"; $tsuri =~ s/,//g; $tsuri = $tsuri+0; $gentotal = $gentotal - $tsuri; } elsif ($oneline =~ /^(信用.+)\s+\\\s(.*)$/) { # 信用でマッチした数をカウントしておく $creditcount++; $cresum = $2; $cresum =~ s/\s//g; print " *信用 $cresum\n"; $cresum =~ s/,//g; $cresum = $cresum+0; $credittotal = $credittotal + $cresum; } elsif ($oneline =~ /^両替\s+$/) { print " 両替\n"; } else { print $oneline."\n"; } } print "\n"; } close (IN); # close (OUT); # 集計処理 print "---- T O T A L ----\n"; print "現金つり計 ".$gentotal."\n"; print "信用計 ".$credittotal."\n"; print "現金つり計+信用計 "; print $gentotal + $credittotal; print "\n"; print "--------\n"; # クロスチェック用(小計計が狂わないように中止した会計は最初でスキップ) print "小計計 ".$subtotal."\n"; print "差額 ".($subtotal - $gentotal - $credittotal)."\n"; print "--------\n"; print "小計マッチ数 ".$subcount."\n"; print "現金マッチ数 ".$cashcount."\n"; print "信用マッチ数 ".$creditcount."\n"; print "金銭処理数差 ".($subcount - $cashcount - $creditcount)."\n"; print "--------\n";
perl4レベルで適当に文字列処理と計算をさせているだけなので、もっと出来る人が全面的に書き換えてくれる事を願いつつ恥を忍んで公開します。