EC-CUBEとクロネコヤマト送り状発行ソフトB2(出力編)

宅配便で出荷するとき、かならず宅配用の伝票に記入する作業が必要になります。これを毎日手書きするのは大変です。それに間違いのもとですね。それで、ヤマト運輸さんであればB2という伝票印刷用のソフトを無料で配布しています。このB2にはCSVファイル形式の宅配先のリストを取り込むという機能がありまして、これを上手に使えば手書きの手間も転記のミスも一気に解消できると思います。
今回はそんなB2に対応したCSVファイルを出力する機能を追加するというカスタマイズをご紹介したいと思います。出力形式はB2基本レイアウトをもとにしています。受注管理にはもともとCSVダウンロードがありますが、それとは別にB2 CSVボタンとして用意してみました。基本的な構造はデフォルトのCSVダウンロードと同じようになっています。
b2csv
 
\data\Smarty\templates\default\admin\order\index.tplに以下のようなかんじで通常のCSV DOWNLOADの横にボタンを追加しています。

<td><a href="#" onmouseover="chgImg('<!--{$TPL_DIR}-->img/contents/btn_csv_onb2.jpg','btn_csv_b2');" onmouseout="chgImg('<!--{$TPL_DIR}-->img/contents/btn_csv_b2.jpg','btn_csv_b2');"    onclick="fnModeSubmit('csv_b2','','');" ><img src="<!--{$TPL_DIR}-->img/contents/btn_csv_b2.jpg" width="99" height="22" alt="CSV DOWNLOAD" border="0" name="btn_csv_b2" id="btn_csv_b2"></a></td>


まずdtb_csvに以下の項目にあわせたINSERT文を流します。デフォルトでcsv_idは5まで使ってあるのでcsv_id=6として新規に追加しています。

csv_idcoldisp_namerankstatuscreate_dateupdate_date
6order_idお客様管理番号11now()now()
6payment_method送り状種別21now()now()
6null as cool_feeクール区分31now()now()
6null as orderslip_no伝票番号41now()now()
6null as send_date出荷予定日51now()now()
6deliv_dateお届け予定日61now()now()
6deliv_time配達時間帯71now()now()
6null as deliv_code届け先コード81now()now()
6(deliv_tel01 || \'-\' || deliv_tel02 || \'-\' || deliv_tel03) as deliv_telお届け先電話番号91now()now()
6null as deliv_tel_branchお届け先電話番号枝番101now()now()
6(deliv_zip01 || \'-\' || deliv_zip02) as deliv_zipお届け先郵便番号111now()now()
6((SELECT pref_name FROM mtb_pref WHERE pref_id = cast(deliv_pref as int4)) || deliv_addr01) AS deliv_addrお届け先住所121now()now()
6deliv_addr02お届け先住所アパートマンション名131now()now()
6null as deliv_company_name1お届け先会社・部門名1141now()now()
6null as deliv_company_name2お届け先会社・部門名2151now()now()
6(deliv_name01 || deliv_name02) as deliv_nameお届け先名161now()now()
6(deliv_kana01 || deliv_kana02) as deliv_kanaお届け先名略称カナ171now()now()
6null as term_respect敬称181now()now()
6null as irainushi_codeご依頼主コード191now()now()
6(order_tel01 || \'-\' || order_tel02 || \'-\' || order_tel03) AS irainushi_telご依頼主電話番号201now()now()
6null as irainushi_tel2ご依頼主電話番号枝番211now()now()
6(order_zip01 || \'-\' || order_zip02) AS irainushi_zipご依頼主郵便番号221now()now()
6((SELECT pref_name FROM mtb_pref WHERE pref_id = cast(order_pref as int4)) || order_addr01) AS irainushi_addrご依頼主住所231now()now()
6order_addr02 as irainushi_addr2ご依頼主住所アパートマンション名241now()now()
6(order_name01 || order_name02) as irainushi_nameご依頼主名251now()now()
6(order_kana01 || order_kana02) as irainushi_kanaご依頼主略称カナ261now()now()
6null as product_code_kuroneko1品名コード1271now()now()
6null as product_name_kuroneko1品名1281now()now()
6null as product_code_kuroneko2品名コード2291now()now()
6null as product_name_kuroneko2品名2301now()now()
6null as baggage1荷扱い1311now()now()
6null as baggage2荷扱い2321now()now()
6order_id as entry_news記事331now()now()
6payment_totalコレクト代金引換額(税込)341now()now()
6null as daikinhikikae_taxコレクト内消費税額等351now()now()
6null as store_stock営業所止置き361now()now()
6null as store_code営業所コード371now()now()
6null as issue_num発行枚数381now()now()
6null as print_number個数口枠の印字391now()now()
6null as charge_custom_codeご請求先顧客コード401now()now()
6null as charge_type_codeご請求先分類コード411now()now()
6null as freight_num運賃管理番号421now()now()

クール便のカスタマイズが入れてある場合はここにクール便の料金が入るようにします。下記の①で紹介している部分は、受注完了時にクール便料金を受注テーブルに入れることによって判定を行っています。
 

次にCSVを出力する部分です。\data\class\pages\admin\order\LC_Page_Admin_Order.phpでもともと受注情報をCSV出力している部分があるのでこの部分を参考にしています。POSTされたmodeによって処理が場合分けされているので “case ‘csv’:” を元にB2用を追加してみます。

                case 'csv_b2':
                    require_once(CLASS_EX_PATH . "helper_extends/SC_Helper_CSV_Ex.php");
                    $objCSV = new SC_Helper_CSV_Ex();
                    // オプションの指定
                    $option = "ORDER BY $order";

                    // CSV出力タイトル行の作成
                    $arrCsvOutput = SC_Utils_Ex::sfSwapArray($objCSV->sfgetCsvOutput(6, " WHERE csv_id = 6 AND status = 1"));

                    if (count($arrCsvOutput) <= 0) break;

                    $arrCsvOutputCols = $arrCsvOutput['col'];
                    $arrCsvOutputTitle = $arrCsvOutput['disp_name'];
                    $head = SC_Utils_Ex::sfGetCSVList($arrCsvOutputTitle);
                    $data = $objCSV->lfGetCSVB2("dtb_order", $where, $option, $arrval, $arrCsvOutputCols);

                    // CSVを送信する。
                    SC_Utils_Ex::sfCSVDownload($head.$data);
                    exit;
                    break;

\data\class\helper\SC_Helper_CSV.phpの中にlfGetCSVがありますがそれを参考にlfGetCSVB2を作ります。まぁほぼ同じものですね・・・。lfMakeCSVB2も同じようにlfMakeCSVを参考につくってB2用に項目を調整しています。

    // CSV出力データを作成する。(B2用)
    function lfGetCSVB2($from, $where, $option, $arrval, $arrCsvOutputCols = "") {

        $cols = SC_Utils_Ex::sfGetCommaList($arrCsvOutputCols);

        $objQuery = new SC_Query();
        $objQuery->setOption($option);

        $list_data = $objQuery->select($cols, $from, $where, $arrval);

        $max = count($list_data);
        if (!isset($data)) $data = "";
        for($i = 0; $i < $max; $i++) {
            // 各項目をCSV出力用に変換する。
            $data .= $this->lfMakeCSVB2($list_data[$i]);
        }
        return $data;
    }

    // 各項目をCSV出力用に変換する。(B2用)
    function lfMakeCSVB2($list) {
        define('INVOICE_HATU',    '0'); // 発払い
        define('INVOICE_COLLECT', '2'); // コレクト

        define('COOL_NORMAL', '0'); // クール:通常
        define('COOL_FREEZE', '1'); // クール:冷凍
        define('COOL_REFRIG', '2'); // クール:冷蔵

        define('B2_HINMEI1',  '食品');       // 品名1                                    //・・・⑤
        define('B2_HINMEI2',  'その他');     // 品名2
        define('B2_BAGGAGE1', 'ワレ物注意'); // 荷扱い1
        define('B2_BAGGAGE2', '天地無用');   // 荷扱い2
        define('CHARGE_CUSTOM_CODE', '00000000000'); // ご請求先顧客コード
        
        $arrDelivTime = array("午前中"=>"0812",
                              "12:00~14:00"=>"1214",
                              "14:00~16:00"=>"1416",
                              "16:00~18:00"=>"1618",
                              "18:00~20:00"=>"1820",
                              "20:00~21:00"=>"2021");
        $line      = "";
        $send_type = "";
        $daibiki = 0;
        $arrInfo = SC_Helper_DB::sf_getBasisData();
        $shop = array("irainushi_zip"=>$arrInfo['zip01'].'-'.$arrInfo['zip02'],
                      "irainushi_addr"=>$this->arrPref[$arrInfo['pref']].$arrInfo['addr01'],
                      "irainushi_addr2"=>$arrInfo['addr02'],
                      "irainushi_tel"=>$arrInfo['tel01'].'-'.$arrInfo['tel02'].'-'.$arrInfo['tel03'],
                      "irainushi_name"=>$arrInfo['company_name'].'('.$arrInfo['shop_name'].')',
                      "irainushi_kana"=>mb_convert_kana($arrInfo['company_kana'].' '.$arrInfo['shop_kana'], "k")
        );

        reset($list);
        while(list($key, $val) = each($list)){
            $tmp = "";
            switch($key) {
            case 'irainushi_kana':
                $val = mb_convert_kana($val, "k");
            case 'irainushi_zip':
            case 'irainushi_addr':
            case 'irainushi_addr2':
            case 'irainushi_tel':
            case 'irainushi_name':
                $tmp =  $list['irainushi_addr'].$list['irainushi_addr2']
                     == $list['deliv_addr'].$list['deliv_addr02']
                     ?  $shop[$key] : $val;                                               //・・・③
                break;
            case 'payment_method':// 送り状種別
                $send_type = strstr($val, '代金引換') ? INVOICE_COLLECT : INVOICE_HATU;   //・・・②
                $tmp       = $send_type;
                break;
            case 'cool_fee':// クール区別
                $tmp = $val > 0 ? COOL_REFRIG : COOL_NORMAL;                              //・・・①
                break;
            case 'send_date':// 出荷予定
                $tmp = date("Y") . '/' .  date("m") . '/' . date("d");
                break;
            case 'deliv_kana':
                $tmp = mb_convert_kana($val, "k");
                break;
            case 'deliv_date':// お届け予定
                if ($val != "") {
                    $delivDate = mb_strcut($val, 0, 8);
                    $delivDate = split("/", $delivDate);
                    $ts  = mktime(0, 0, 0, $delivDate[1], $delivDate[2], $delivDate[0]);
                    $tmp = date("Y", $ts) . '/' .  date("m", $ts) . '/' . date("d", $ts);
                }
                break;
            case 'deliv_time':// お届け時間
                $tmp = $arrDelivTime[$val];                                              //・・・②
                break;
            case 'term_respect':// 敬称
                $tmp = $val == "" ? '様' : $val;
                break;
            case 'product_name_kuroneko1':// 品名1
                $tmp = B2_HINMEI1;
                break;
            case 'product_name_kuroneko2':// 品名2
                $tmp = B2_HINMEI2;
                break;
            case 'baggage1':// 荷扱い1
                $tmp = B2_BAGGAGE1;
                break;
            case 'baggage2':// 荷扱い2
                $tmp = B2_BAGGAGE2;
                break;
            case 'entry_news':// 記事(受注IDを表示)
                $tmp = "注文番号:" . $val;                                              //・・・④
                break;
            case 'payment_total':// コレクト代引
                $daibiki = $send_type == INVOICE_COLLECT ? $val : 0;
                $tmp     = $daibiki;
                break;
            case 'daikinhikikae_tax':// コレクト代引税
                $tmp = floor($daibiki * 5/105);
                break;
            case 'charge_custom_code':// ご請求先顧客コード
                $tmp = CHARGE_CUSTOM_CODE;
                break;
            default:
                $tmp = $val;
                break;
            }
            $tmp = ereg_replace("\"", "\"\"", $tmp);
            $line .= "\"".$tmp."\",";
        }
        // 文末の","を変換
        $line = $this->replaceLineSuffix($line);
        return $line;
    }

①クール便についてはあらかじめ受注情報に金額を持たせるようにカスタマイズを入れています。今回は金額の有無でのみ判定をしており、冷凍の判定は入っていません。冷凍と冷蔵の区別が必要なものについては受注完了時にフラグを持たせるよう改造してもいいですね。
 
②代金引換や時間指定については文字列から判定しちゃってます。データの持ち方をそれぞれのサイトの環境にあわせる必要がありますね。
 
③ご依頼主住所についてですが、ここは落とし穴があって、荷物の依頼主は通常はショップ様なのですが、ギフトの場合は依頼主部分にご注文者様を表示しないといけません。そこで、送り先住所と依頼主住所を比較して異なる場合はギフト配送、という判定を行って依頼主住所の表示を変更しています。
 
④「記事」という項目がありますが、ここには受注番号を表示しています。伝票を見たときにその伝票がどの受注に対してのものなのかわかるようにするためですね。
 
⑤品名や荷扱い、請求先顧客コードなどについてはそれぞれのお店にあわせて設定してください。
 
もちろんB2だけじゃなくて佐川急便の飛伝などでも対応可能です。よければご相談ください。
http://ec-cube.systemfriend.co.jp/inquiry/
 
 
こちらでB2を一部利用したスムーズな出荷処理についても紹介しています。リンク先の記事に書いてある出荷CSV取り込み処理を次回ご紹介したいと思います。