[eccube3]帳票出力プラグインをいじる

ちょっとした加工

やりたいこと

表示項目を追加したい。

プラグイン

3.0系|帳票出力プラグイン|株式会社イーシーキューブ(EC-CUBE開発元)
https://www.ec-cube.net/products/detail.php?product_id=959

仕組み

FPDFとかいう、PHP上でPDFを生成するライブラリを噛ませて納品書とかを書き出してる。

参考

【EC-CUBE3系】納品書にお届け先の情報を出力する | a special kind of humor reconciled
https://www.skhr.work/tech/20181113/ec-cube-print-receipt/

参考というか、色々考えた挙げ句これに倣って終了した。

編集ファイル

app/Plugin/OrderPdf/Service/OrderPdfService.php
これ一つでPDFの出力内容やら配置を管理している。

いじり方の考え方

出力する内容はグループに分かれていて、ショップ情報エリアとか商品名エリアとか金額エリアとか購入者情報エリアとか受注情報エリアとかそんな感じ。
自分が追加したい内容に合わせて、そのエリア内に書き込む。

protected function renderOrderData(Order $Order){ *** }

みたいな感じで囲ってあるし、コメントアウトで説明もあるからなんとなく読めばわかると思う。

    //note
    $this->SetFont(self::FONT_SJIS, '', 8);
    $text = $Order->getNote();
    $this->lfText(16, 205, $text, 11);

PDFへの出力は簡潔にいえばこういうことで、(1行目)フォントを指定して(2行目)出力したい内容を指定して(3行目)出力位置を指定する。

$this->lfText(16, 205, $text, 11);

これの16と205はそれぞれX座標(横)、Y座標(縦)になっている。
イラレとかPPTのオブジェクトの組み合わせみたいなイメージで組んでいく。

出力しないと雰囲気がわからない上にプラグインの更新はキャッシュを消してもしばらくかかったりして根気がいる。

理解の途中だけどメモ

お届け日、お届け時間の表示

大前提として、複数箇所のお届け先は考慮していないので注意。

$Shippings = $Order->getShippings();
$i = 1;
$this->SetFont(self::FONT_SJIS, 'B', 15);
foreach ($Shippings as $Shipping) { // お届け日存在チェック
    if (!is_null($Shipping->getShippingDeliveryDate())) {
        $deliveryDate = $Shipping->getShippingDeliveryDate()->format('Y/m/d')."\n";
    }
}
$this->lfText(60, 125, $deliveryDate, 10);
foreach ($Shippings as $Shipping) { // お届け時間存在チェック
    if (!is_null($Shipping->getShippingDeliveryTime())) {
        $deliveryTime = $Shipping->getShippingDeliveryTime()."\n";
    }
}
$this->lfText(60, 135, $deliveryTime, 10);

これを

protected function renderOrderData(Order $Order)

これの中に入れると、お届け日とお届け時間(※注文時に指定した希望日時)が表示される。表示位置は「ご注文日」の右側。項目名はテンプレートになるPDFに載せておく。

テンプレートPDF

FPDFはPHP上で指定した内容を書き出すだけじゃなく、テンプレートを指定できる。「app/template/admin/OrderPdf/nouhinsyo1.pdf」を見ればわかるんだけど、一部の罫線とか項目名はプラグインじゃなくてPDF内で予め用意されている。

支払い方法の表示

項目名の設置は上記の通り、テンプレートのPDFに記載。
ゴシック系で10ptくらいの太字でやれば元々のやつに寄せられる。
手間じゃなければ作り直しても良いんじゃないかな。

//支払い方法 ここから
$this->SetFont(self::FONT_SJIS, '', 8);
$text = $Order->getPayment();
$this->lfText(100, 125, $text, 10);
//支払い方法 ここまで

これを

protected function renderOrderData(Order $Order)

ここに入れる。

備考欄のカスタマイズ

プラグイン側で用意してる備考欄に、購入時の問い合わせ内容と受注マスターのショップメモを挿入する方法。

まずは引数をいじる。

// 備考を描画する</code>
// $this->renderEtcData($formData);
$this->renderEtcData($order, $formData);

いじりすぎて元の行数がよくわかんなくなってるけど、大体180行目あたりのやつ。「,」で区切れば複数引っ張れることを確認。

/**
 * PDFに備考を設定数.
 *
 * @param array $formData</code><br>
 *
// protected function renderEtcData(array $formData)
protected function renderEtcData(Order $Order, array $formData)

300行目かな、最初の宣言に合わせてラッピングしているところも修正。
その直下に以下を追加。

//「お問い合わせ内容」追加 ここから
if (!is_null($Order->getMessage())) {
$text .= "< ご注文時のお問い合わせ >\n".$Order->getMessage()."\n\n";
}
//「お問い合わせ内容」追加 ここまで
//「ショップ用メモ欄」追加 ここから
if (!is_null($Order->getNote())) {
$text .= $Order->getNote()."\n\n";
}
//「ショップ用メモ欄」追加 ここまで

上から順に書き出されるので、全部の欄に記入が合った場合は「お問い合わせ内容→ショップ用メモ欄→プラグイン備考欄」の順で書き出される。
順番を変えたければ「$text .=」のところの順番が変わるように編集すること。

受注情報詳細ページで帳票出力できるようにする

商品マスターからしか出力できないんで、個別ページからも書き出せるようにする。

アクセスさえすれば出力するっていう仕組みだから、リンクを挿入してしまえばいい。

「/admin/Order/edit.twig」が該当ページで、それをいじる。
「src/Eccube/Resource/template/admin/Order/」にあるやつを「app/template/admin/Order/」にコピーする。

コピーしたedit.twigを開いて、以下を挿入。
挿入箇所はどこでもいい、既存のスタイルでボタンっぽくできるので流用してる。

{% if Order.id is not empty %}
<p><a class="btn btn-default" href='{{ url('plugin_admin_order_pdf') }}?ids{{ Order.id }}=on'">帳票出力</a></p>
{% endif %}

新規登録時に表示しても意味がないので、「受注IDがあれば表示」のif文で括って出力のリンクを表示。
帳簿URLのパラメータに受注IDを突っ込んだら該当のやつが出るっていう仕組みなんで、その部分を補完。

購入詳細情報の表のカスタマイズ

表部分は予め各セルの幅が決められていて、文字数が幅を超えると改行される。
普通に使ってる分には問題ないんだけど、先頭セルが改行されてない状態で2番目以降が改行されるとセルが崩れる。とりあえず表示するテキストを変更してPDFを書き出してみて、崩れてたら対策しなければいけない。

  • 文字数を減らす
  • 文字サイズを下げる
  • セルの幅を変更する

文字サイズは一元管理してるので部分的に手を入れるのは無理というか面倒というか。
文字数を減らせない、調整してもはみ出ちゃう場合はセルの幅を変更する。

/app/Plugin/OrderPdf/Service/OrderPdfService.php
を開いて100行目あたりにあるやつを編集する。デフォルトだと以下の通り。

$this->widthCell = array(110.3, 12, 21.7, 24.5);

合計値「168.5」を維持しつつ修正。これが変わると他との兼ね合いで調整をする必要が出てきてめんどくさい。

海外住所プラグインとの兼ね合い

ECCUBE3には国の設定がそもそもあって、IDと国名がセットになってマスターデータに保存されている。デフォだと日本扱いで、プラグインとかカスタマイズとかで指定できるようになる。

取得ってどうやるの?って場合、以下の通り。

購入者住所の出力

    protected function renderOrderData(Order $Order)
    {
~
        $this->lfText(27, 55, $Order->getCountry(), 10); //国名
        $this->lfText(27, 59, $Order->getPref()->getId(), 10); //国ID
~
    }

IDの拾い方が違うんで混乱する。

で、国IDが拾えるようになったのでifで国内・国外の振り分けができるようになった。

$japan_id = '392';
if($Order->getPref()->getId() == $japan_id){
    //国内枠
}else{
    //国外枠
}

書くならOrderで宣言してるところ、たとえば「購入者情報部」のところね。
じゃないと$Orderが拾えないからね。

  • 郵便番号
  • 電話番号
  • FAX番号

この3種は受注情報に格納されてなくて、プラグイン用のDBに格納されてる。
受注IDが紐付いてるのでそれを経由して出力する必要がある。
方法は以下の通り。

        $telOverseas = '';
        $faxOverseas = '';
        $zipcodeOverseas = '';
        $OverseasAddressOrder = $this->app['eccube.plugin.overseas_address.repository.order']->findOneBy(array('Order' => $Order->getId()));
        if ($OverseasAddressOrder) {
            $telOverseas = $OverseasAddressOrder->getTelOverseas();
            $faxOverseas = $OverseasAddressOrder->getFaxOverseas();
            $zipcodeOverseas = $OverseasAddressOrder->getZipcodeOverseas();
        }

「$OverseasAddressOrder = ~」のところがネック。
上記のifで海外住所だった場合の枠で、任意の変数を書き込めばいい。

$OverseasAddressOrder = $this->app['eccube.plugin.overseas_address.repository.order']->findOneBy(array('Order' => $Order->getId()));

これは要するに「DBの特定のテーブルに格納されてるデータをIDを指定して抽出する」っていう内容。

app['eccube.plugin.overseas_address.repository.order']

この[]の中身は元になるプラグインで宣言されているのでそれを引っ張ってくることになる。
今回のケースだと以下のファイルが該当する。
/app/Plugin/OverseasAddress/ServiceProvider/OverseasAddressServiceProvider.php

findOneBy(array('Order' => $Order->getId()))

この部分がIDを指定した抽出にあたる内容。「Order」がどっから来たかっていうと、これも元のプラグインで宣言されている。このあたりはDBを見ても何もわからん。
/app/Plugin/OverseasAddress/Entity/OverseasAddressOrder.php

配送先住所の出力

$zipcodeOverseas = '';
$Shipping = $Order->getShippings()[0];
$OverseasAddressShipping = $this->app['eccube.plugin.overseas_address.repository.shipping']->findOneBy(array('Shipping' => $Shipping));
if ($OverseasAddressShipping) {
    $zipcodeOverseas = $OverseasAddressShipping->getZipcodeOverseas();
}
$japan_id = '392';
if($Shipping->getPref()->getId() == $japan_id){
    //国内
    $text = '〒 '.$Shipping->getZip01().' - '.$Shipping->getZip02();
    $this->lfText(80, 125, $text, 10,'B');
    // お届け先都道府県+住所1
    $text = $Shipping->getPref().$Shipping->getAddr01();
    $this->lfText(80, 129, $text, 10,'B');
    $this->lfText(80, 133, $Shipping->getAddr02(), 10,'B'); //お届け先住所2
    $text = $Shipping->getName01().' '.$Shipping->getName02();
    $this->lfText(80, 137, $text, 10,'B');
}else{
    //国外
    $text = $Shipping->getAddr02();//住所2
    $this->lfText(80, 125, $text, 10);
    $this->lfText(80, 129, $Shipping->getAddr01(), 10);//住所1
    $this->lfText(80, 133, $zipcodeOverseas, 10);//郵便番号
    $this->lfText(80, 137, $Shipping->getCountry(), 10);//国名
    $text = $Shipping->getName01().' '.$Shipping->getName02();//名前
    $this->lfText(80, 141, $text, 10,'B');
}

ちょっと時間がないんでざっくりと。
表示位置は配送業者あたりの高さに合わせてる。

これは最初の1住所しか対応してないんで、配送先複数対応する場合は要調整。
最初の「$Sipping」で1箇所だけに指定してる。
複数出したいならforeachとか使って回す感じになる。

敬称について

会員は性別の欄があるんでこんな感じでやれる。

        // 購入者氏名
        $gender = $Order->getSex();
        if($gender == 1){
            $sex = 'Mr.';
        }else if($gender == 2){
            $sex = 'Ms.';
        }
        $text = $sex.' '.$Order->getName01().' '.$Order->getName02();
        $this->lfText(27, 65, $text, 11);

非会員状態とか配送先情報については性別項目がないんで使えない。

コメント

タイトルとURLをコピーしました