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

前回に引き続き今回はヤマト運輸のB2からCSVファイルの取り込み編です。B2は出荷したデータをCSV出力することができますよね。それをEC-CUBEに取り込んで、対応した受注のステータス変更などを一括でしてしまえば、いろいろな作業が減らせるということなのです。これは出荷の流れをスムーズにする方法の工夫4でも紹介しています。
これを行うと次のようなことができてしまいます。
・一括で注文ステータスを更新できて
・一括で伝票番号を取り込める
・一括で伝票番号の記載された配送完了メールを送信できる
・一括でクレジットの売上処理ができる

取り込みには以下のように、CSVを読み込む「出荷処理」ページを1ページ追加しました。追加したクラスのファイルは\data\class\pages\admin\products\LC_Page_Admin_Products_UploadCSV.phpなどのCSVアップロード機能を元に作成しています。
ordersend
 
実際にアップロードした際の処理は、大体以下のような流れになっています。

        define('B2_CSV_ORDERID_COL',     0);// 読み込んだB2CSV 受注IDが入っている列                           ・・・①
        define('B2_CSV_KURONEKO_NO_COL', 3);// 読み込んだB2CSV 伝票番号が入っている列
        
        switch($_POST['mode']) {
        case 'csv_upload':
            $err = false;
            // エラーチェック
            $arrErr['csv_file'] = $this->objUpFile->makeTempFile('csv_file');

            if($arrErr['csv_file'] == "") {
                $arrErr = $this->objUpFile->checkEXISTS();
            }

            // 実行時間を制限しない
            set_time_limit(0);
            // 出力をバッファリングしない(==日本語自動変換もしない)
            ob_end_clean();
            // IEのために256バイト空文字出力
            echo str_pad('',256);

            if(empty($arrErr['csv_file'])) {
                // 一時ファイル名の取得
                $filepath = $this->objUpFile->getTempFilePath('csv_file');
                // エンコード
                $enc_filepath = SC_Utils_Ex::sfEncodeFile($filepath,
                                                          CHAR_CODE, CSV_TEMP_DIR);
                $fp = fopen($enc_filepath, "r");

                // 無効なファイルポインタが渡された場合はエラー表示
                if ($fp === false) {
                    SC_Utils_Ex::sfDispError("");
                }

                // レコード数を得る
                $rec_count = $this->lfCSVRecordCount($fp);

                $line   = 0;      // 行数
                $regist = 0;    // 登録数

                $objQuery = new SC_Query();

                echo "■ 処理開始 <br/><br/>\n";

                while(!feof($fp) && !$err) {
                    $arrCSV = fgetcsv($fp, CSV_LINE_MAX);

                    // 行カウント
                    $line++;
                    // 項目数カウント
                    $max = count($arrCSV);
                    // 受注番号チェック
                    $order_id = $arrCSV[B2_CSV_ORDERID_COL];
                    $arrErr = $this->lfErrorCheck(array("order_id"=>$order_id));

                    // 項目数が1以下の場合は無視する
                    if($line <= 1) {
                        continue;
                    }
                    // 項目数が1以下の場合は無視する
                    if($max <= 1) {
                        continue;
                    }
                    // 入力エラーの場合
                    if(0 < count($arrErr)) {
                        $this->printError($line." / ".$rec_count. "行目 " . $arrErr['order_id'] .  "\n");
                        continue;
                    }

                    // 受注情報の取得
                    $arrData = $objQuery->select("*", "dtb_order", "order_id = ? AND del_flg = 0", array($order_id));
                    $arrOrder = $arrData[0];

                    // 受注IDが存在しない場合
                    if(count($arrOrder) < 1) {
                        $this->printError($line." / ".$rec_count. "行目 (受注番号:".$arrCSV[0]."は存在しません)\n");
                        continue;
                    }
                    // 受注ステータスが発送済みの場合                                                         ・・・②
                    if($arrOrder['status'] == ORDER_DELIV) {
                        $this->printError($line." / ".$rec_count. "行目 (受注番号:".$arrCSV[0]."は受注ステータスが". $this->arrORDERSTATUS[$arrOrder['status']]."です)\n");
                        continue;
                    }

                    // ステータスと伝票番号の更新
                    $kuroneko = $arrCSV[B2_CSV_KURONEKO_NO_COL];
                    $this->lfUpdateOrderStatus($objQuery, $arrOrder['order_id'], $kuroneko, $line);

                    // クレジットの判定と売り上げ処理
                    $arrResult = $this->lfPaygentCredit($arrOrder);
                    list($paygent, $credit) = $arrResult;

                    echo "\n<br />";

                    $regist++;
                }
                fclose($fp);

                echo "■" . $regist . "件のレコードを更新しました。";
            } else {
                foreach($arrErr as $val) {
                    $this->printError($val);
                }
            }
            echo "<br/><a href=\"javascript:window.close()\">→閉じる</a>";
            flush();
            exit;
            break;
        default:
            break;
        }

//-----------------------------------------------------------------------------------------------------------------------//

    /**
     * 受注ステータスの更新を行う.
     *
     * @param SC_Query $objQuery SC_Queryインスタンス
     * @param integer $order_id 受注番号
     * @param string|integer $kuroneko_no クロネコ伝票番号
     * @return vuoid
     */
    function lfUpdateOrderStatus($objQuery, $order_id, $kuroneko_no) {
        $order_status = ORDER_DELIV; // 発送済みステータスに

        $sqlval = array();
        $sqlval['update_date'] = now();
        $sqlval['commit_date'] = now();
        $sqlval['status']      = $order_status;
        $sqlval['kuroneko_no'] = $kuroneko_no;

        $objQuery->update("dtb_order", $sqlval, "order_id = ?", array($order_id));                            //・・・③
        
        //メールの配信
        $objMail = new SC_Helper_Mail_Ex();
        $objMail->sfSendOrderMail($order_id, 3);                                                              //・・・④
    }



①B2から出力したCSVの何列目に注文番号と伝票番号が出力されているかで設定を変更します。ちなみに注文番号が最初に出力されているのはB2用CSV出力編で「お客様管理番号」の項目に注文番号を入れているからです。(この記事はB2用CSV出力編で紹介したCSVを取り込んだあとに B2から出力されるCSVデータを元にしています。)
 
②受注ステータスがすでに「発送済み」の場合は処理を中断しています。このCSV取り込み処理では、発送完了メールの送信も行っているので、重複処理・送信を避けるためですね。
 
③受注データにステータスの更新と伝票番号の取り込みを行っています。あらかじめ受注テーブルに伝票番号用のカラムを追加しておく必要があります。取り込んだ伝票番号は受注編集画面から確認できるようにしておくとよいです。
 
④発送完了メール用のテンプレートをあらかじめ設定しておき、そのテンプレートIDを指定します。メールテンプレートの受注情報が動的に挿入される部分には、あらかじめ伝票番号が表示されるように変更しておく必要があります。また、メールのヘッダフッタ部分にクロネコさんの伝票検索が行えるページのリンクを表記しておくと親切ですね。(http://www.kuronekoyamato.co.jp/)

その他にもクレジット決済の売上処理を自動で行うようにすることも可能です。クレジット処理は注文時はオーソリ(与信)だけで、出荷後に売上確定するという手順が今後は主流になっていくものと思われます。現状でもオーソリと売上確定を別々に実施されているショップの場合、売上確定処理を1件ずつ処理するのは手間がかかると思います。そこでこのCSV取り込み処理を行うタイミングでクレジット決済のものについては売上を行うと大変便利です。この部分に関しては決済モジュールに手を入れる必要があります。各代行会社によって仕様が異なっています。
もちろんB2以外に佐川急便の飛伝などでも対応可能ですので、よければご相談ください。
http://ec-cube.systemfriend.co.jp/inquiry/