日: 2009年12月29日

【EC-CUBE】会員ランクを設定し、ランクごとの割引率で販売する その3

さて、最後です。(は~、疲れた;)
最後にテンプレ関係を直していきます。

【ステップ3】

・/data/Smarty/templates/default/admin/customer/index.tpl (L146あたり)

<tr>
                                <td bgcolor=”#f2f1ec” width=”110″>会員状態</td>
                                <td bgcolor=”#ffffff” width=”499″ colspan=”3″><!–{html_checkboxes name=”status” options=$arrStatus separator=”&nbsp;” selected=$arrForm.status}–></td>
                            </tr>
                             <tr>
                                <td bgcolor=”#f2f1ec” width=”110″>会員ランク</td>
                                <td bgcolor=”#ffffff” width=”499″ colspan=”3″><!–{html_checkboxes name=”customer_rank” options=$arrCustomer_rank separator=”&nbsp;” selected=$arrForm.customer_rank}–></td>
                            </tr>

・/data/Smarty/templates/default/admin/customer/edit.tpl (L126あたり)

        <table width=”678″ border=”0″ cellspacing=”1″ cellpadding=”8″ summary=” “>

         <tr>
          <td bgcolor=”#f2f1ec” width=”190″>顧客ID<span> *</span></td>
          <td bgcolor=”#ffffff” width=”527″><!–{$list_data.customer_id|escape}–></td>
         </tr>
         <tr>
          <td bgcolor=”#f2f1ec” width=”190″>会員状態<span> *</span></td>
          <td bgcolor=”#ffffff” width=”527″>
           <span><!–{$arrErr.status}–></span>
           <input type=”radio” name=”status”value=1 id=”no_mem” <!–{if $list_data.status == 1}–> checked=”checked” <!–{/if}–> <!–{if $list_data.status == 2}–>disabled<!–{/if}–>><label for=”no_mem”>仮会員</label>
           <input type=”radio” name=”status”value=2 id=”mem”<!–{if $list_data.status == 2}–> checked=”checked” <!–{/if}–>><label for=”mem”>本会員</label>
          </td>
         </tr>

 <tr>
          <td bgcolor=”#f2f1ec” width=”190″>会員ランク<span> *</span></td>
          <td bgcolor=”#ffffff” width=”527″>
           <span><!–{$arrErr.customer_rank}–></span>
           <!–{html_radios name=”customer_rank” options=$arrCustomer_rank separator=” ” selected=$list_data.customer_rank}–>
          </td>
         </tr>

・/data/Smarty/templates/default/admin/customer/edit_confirm.tpl (L100あたり)

<td width=”190″ bgcolor=”#f2f1ec”>
      会員状態<span> *</span></td>
<td width=”527″ bgcolor=”#ffffff”>
      <!–{if $arrForm.status == 1}–>仮会員<!–{else}–>本会員<!–{/if}–>

</td>
<td width=”190″ bgcolor=”#f2f1ec”>
      会員ランク<span> *</span></td>
<td width=”527″ bgcolor=”#ffffff”>
      <!–{if $arrForm.customer_rank == 5}–>ランク5<!–{elseif $arrForm.customer_rank == 4}–>ランク4<!–{elseif $arrForm.customer_rank == 3}–>ランク3<!–{elseif $arrForm.customer_rank == 2}–>ランク2<!–{else}–>ランク1<!–{/if}–></td>
 

・/data/Smarty/templates/default/admin/mail/index.tpl (L145あたり)

<tr>
                                <td bgcolor=”#f2f1ec” width=”110″>会員ランク</td>
                                <td bgcolor=”#ffffff” colspan=”3″>
                                    <!–{if $arrErr.customer_rank}–><span><!–{$arrErr.customer_rank}–></span><!–{/if}–>
                                    <span style=”<!–{$arrErr.customer_rank|sfGetErrorColor}–>”>
                                   <!–{html_checkboxes_ex name=”customer_rank” options=$arrCustomer_rank separator=”&nbsp;” selected=$list_data.customer_rank}–>
                                    </span>
                                </td>
                            </tr>

<tr>
                                <td bgcolor=”#f2f1ec” width=”110″>メールアドレス</td>
                                <td bgcolor=”#ffffff” colspan=”3″>
                                    <!–{if $arrErr.email}–><span><!–{$arrErr.email}–></span><!–{/if}–>
                                    <span style=”<!–{$arrErr.email|sfGetErrorColor}–>”>
                                    <input type=”text” name=”email” maxlength=”<!–{$smarty.const.STEXT_LEN}–>” value=”<!–{$list_data.email|escape}–>” size=”60″    style=”<!–{$arrErr.email|sfGetErrorColor}–>”/>
                                    </span>
                                </td>
                            </tr>

・/data/Smarty/templates/default/admin/mail/query.tpl (L132あたり)

<tr>
           <td bgcolor=”#f0f0f0″ width=”110″>会員ランク</td>
           <td bgcolor=”#ffffff” width=”507″ colspan=”3″><!–{$list_data.customer_rank_disp|default:”(未指定)”}–></td>
          </tr>

<tr>
           <td bgcolor=”#f0f0f0″ width=”110″>メールアドレス</td>
           <td bgcolor=”#ffffff” width=”507″ colspan=”3″><!–{$list_data.email|escape|default:”(未指定)”}–></td>
          </tr>

以上です。
実は、テストは、コミュ版でやっていて、あとから、正式版の対応するソースを探したので、もしかしたら、漏れとかあるかもしれません。多分大丈夫と思いますが、もし、有って気づいたら直します。

【EC-CUBE】会員ランクを設定し、ランクごとの割引率で販売する その2

【ステップ2】

・/data/class/SC_CustomerList.php (L122あたり)

//性別
if (!isset($this->arrSql[‘sex’])) $this->arrSql[‘sex’] = “”;
if ( is_array( $this->arrSql[‘sex’] ) ){
$arrSexVal = $this->setItemTerm( $this->arrSql[‘sex’] ,”sex” );
foreach ($arrSexVal as $data) {
$this->arrVal[] = $data;
}
}

//会員ランク
if (!isset($this->arrSql[‘customer_rank’])) $this->arrSql[‘customer_rank’] = “”;
if ( is_array( $this->arrSql[‘customer_rank’] ) ){
$arrCustomer_rankVal = $this->setItemTerm( $this->arrSql[‘customer_rank’] ,”customer_rank” );
foreach ($arrCustomer_rankVal as $data) {
$this->arrVal[] = $data;
}
}

//職業

(L360あたり)

// 検索用SQL
function getList() {
$this->select = “SELECT customer_id,name01,name02,kana01,kana02,sex,email,tel01,tel02,tel03,pref,status,customer_rank FROM dtb_customer “;
return $this->getSql(0);
}

(L395あたり)

function getMailMagazineColumn($is_mobile= false) {
if($is_mobile == true) {
$email_column = “dtb_customer.email_mobile as email”;
} else {
$email_column = “dtb_customer.email”;
}

$column =”dtb_customer.customer_id,
dtb_customer.name01,
dtb_customer.name02,
dtb_customer.kana01,
dtb_customer.kana02,
dtb_customer.sex,
$email_column,
dtb_customer.tel01,
dtb_customer.tel02,
dtb_customer.tel03,
dtb_customer.pref,
dtb_customer.create_date,
dtb_customer.mailmaga_flg,
dtb_customer.customer_rank”;
return $column;
}

・/data/class/helper/SC_Helper_DB.php (L366あたり)

// 価格の登録
$objCustomer = new SC_Customer();
$objQuery = new SC_Query();
if($objCustomer->isLoginSuccess()) {
$customer_rank = $objCustomer->getValue(‘customer_rank’);
$discount_rank = $objQuery->get(“mtb_customer_discount”, “name”, “rank=?”, array($customer_rank));
if ($discount_rank != “”) {
if ($arrData[‘price02’] != “”) {
$objCartSess->setProductValue($arrCart[‘id’], ‘price’, $arrData[‘price02’]*$discount_rank);
$objPage->arrProductsClass[$cnt][‘uniq_price’] = $arrData[‘price02’]*$discount_rank;
} else {
$objCartSess->setProductValue($arrCart[‘id’], ‘price’, $arrData[‘price01’]*$discount_rank);
$objPage->arrProductsClass[$cnt][‘uniq_price’] = $arrData[‘price01’]*$discount_rank;
}
}else{
if ($arrData[‘price02’] != “”) {
$objCartSess->setProductValue($arrCart[‘id’], ‘price’, $arrData[‘price02’]);
$objPage->arrProductsClass[$cnt][‘uniq_price’] = $arrData[‘price02’];
} else {
$objCartSess->setProductValue($arrCart[‘id’], ‘price’, $arrData[‘price01’]);
$objPage->arrProductsClass[$cnt][‘uniq_price’] = $arrData[‘price01’];
}
}
}

※最後の「}」を忘れないように注意!

・/data/class/helper/SC_Helper_CSV.php(L53あたり)
※これは、もしかしたら不要かも。。。

* デフォルトコンストラクタ.
*/
function SC_Helper_CSV() {
$this->init();

$masterData = new SC_DB_MasterData_Ex();
$this->arrPref = $masterData->getMasterData(“mtb_pref”,
array(“pref_id”, “pref_name”, “rank”));
$this->arrSex = $masterData->getMasterData(“mtb_sex”);
$this->arrDISP = $masterData->getMasterData(“mtb_disp”);
$this->arrRECOMMEND = $masterData->getMasterData(“mtb_recommend”);
$this->arrCustomer_rank = $masterData->getMasterData(“mtb_customer_rank”);
}

・/data/class/page/admin/customer/SC_Page_Admin_Customer.php (L62あたり)

$this->arrJob = $masterData->getMasterData(“mtb_job”);
$this->arrJob[“不明”] = “不明”;
$this->arrSex = $masterData->getMasterData(“mtb_sex”);
$this->arrPageRows = $masterData->getMasterData(“mtb_page_rows”);
$this->arrMAILMAGATYPE = $masterData->getMasterData(“mtb_mail_magazine_type”);
$this->arrCustomer_rank = $masterData->getMasterData(“mtb_customer_rank”);
$this->arrHtmlmail[”] = “すべて”;

(L154あたり)

25 => array(“sql” => “cast(create_date as date) AS create_date”,
“csv” => “create_date”,
“header” => “登録日”),
26 => array(“sql” => “cast(update_date as date) AS update_date”,
“csv” => “update_date”,
“header” => “更新日”),
27 => array(“sql” => “customer_rank”,
“csv” => “customer_rank”,
“header” => “会員ランク”)

);
}

※26 =>・・・の最後に、「,」が入っています。お見逃し無く。
(L188あたり)

// 検索ワードの引き継ぎ
foreach ($_POST as $key => $val) {
switch($key) {
case ‘sex’:
case ‘status’:
case ‘customer_rank’:
$this->arrHidden[$key] = SC_Utils_Ex::sfMergeParamCheckBoxes($val);
if(!is_array($val)) {
$this->arrForm[$key] = split(“-“, $val);
}
break;

・/data/class/page/admin/customer/SC_Page_Admin_Customer_Edit.php(L58あたり)

function init() {
parent::init();
$this->tpl_mainpage = ‘customer/edit.tpl’;
$this->tpl_mainno = ‘customer’;
$this->tpl_subnavi = ‘customer/subnavi.tpl’;
$this->tpl_subno = ‘index’;
$this->tpl_pager = TEMPLATE_DIR . ‘admin/pager.tpl’;
$this->tpl_subtitle = ‘顧客マスタ’;

$masterData = new SC_DB_MasterData_Ex();
$this->arrPref = $masterData->getMasterData(“mtb_pref”, array(“pref_id”, “pref_name”, “rank”));
$this->arrJob = $masterData->getMasterData(“mtb_job”);
$this->arrSex = $masterData->getMasterData(“mtb_sex”);
$this->arrReminder = $masterData->getMasterData(“mtb_reminder”);
$this->arrCustomer_rank = $masterData->getMasterData(“mtb_customer_rank”);
}

(L109あたり)

array( “column” => “reminder”, “convert” => “n” ),
array( “column” => “reminder_answer”, “convert” => “aKV” ),
array( “column” => “mailmaga_flg”, “convert” => “n” ),
array( “column” => “note”, “convert” => “aKV” ),
array( “column” => “point”, “convert” => “n” ),
array( “column” => “status”, “convert” => “n” ),
array( “column” => “customer_rank”, “convert” => “n” )
);

(L320あたり)

$objErr->doFunc(array(“ご性別”, “sex”) ,array(“SELECT_CHECK”, “NUM_CHECK”));
$objErr->doFunc(array(“ご職業”, “job”) ,array(“NUM_CHECK”));
$objErr->doFunc(array(“会員ランク”, “customer_rank”) ,array(“SELECT_CHECK”, “NUM_CHECK”));
if ($array[“password”] != DEFAULT_PASSWORD) {
$objErr->doFunc(array(“パスワード”, ‘password’, PASSWORD_LEN1, PASSWORD_LEN2), array(“EXIST_CHECK”, “ALNUM_CHECK”, “NUM_RANGE_CHECK”));
}

・/data/class/page/admin/mail/SC_Page_Admin_Mail.php (L57あたり)

$masterData = new SC_DB_MasterData_Ex();
$this->arrPref = $masterData->getMasterData(“mtb_pref”, array(“pref_id”, “pref_name”, “rank”));
$this->arrJob = $masterData->getMasterData(“mtb_job”);
$this->arrJob[“不明”] = “不明”;
$this->arrSex = $masterData->getMasterData(“mtb_sex”);
$this->arrCustomer_rank = $masterData->getMasterData(“mtb_customer_rank”);
$this->arrMailType = $masterData->getMasterData(“mtb_mail_type”);
$this->arrPageRows = $masterData->getMasterData(“mtb_page_rows”);
// ページナビ用

(L96あたり)

//—- 検索項目
$this->arrSearchColumn = array(
array( “column” => “name”, “convert” => “aKV”),
array( “column” => “pref”, “convert” => “n” ),
array( “column” => “kana”, “convert” => “CKV”),
array( “column” => “sex”, “convert” => “” ),
array( “column” => “customer_rank”, “convert” => “” ),
array( “column” => “tel”, “convert” => “n” ),
array( “column” => “job”, “convert” => “” ),
array( “column” => “email”, “convert” => “a” ),

(L191あたり)

// 配信形式
$list_data[‘htmlmail_disp’] = $this->arrHtmlmail[$list_data[‘htmlmail’]];

// 性別の変換
if (count($list_data[‘sex’]) > 0) {
foreach($list_data[‘sex’] as $key => $val){
$list_data[‘sex’][$key] = $this->arrSex[$val];
$sex_disp .= $list_data[‘sex’][$key] . ” “;
}
$list_data[‘sex_disp’] = $sex_disp;
}

// 会員ランクの変換
if (count($list_data[‘customer_rank’]) > 0) {
foreach($list_data[‘customer_rank’] as $key => $val){
$list_data[‘customer_rank’][$key] = $this->arrCustomer_rank[$val];
$customer_rank_disp .= $list_data[‘customer_rank’][$key] . ” “;
}
$list_data[‘customer_rank_disp’] = $customer_rank_disp;
}

// 職業の変換
if (count($list_data[‘job’]) > 0) {
foreach($list_data[‘job’] as $key => $val){
$list_data[‘job’][$key] = $this->arrJob[$val];
$job_disp .= $list_data[‘job’][$key] . ” “;
}
$list_data[‘job_disp’] = $job_disp;
}

}

【EC-CUBE】会員ランクを設定し、ランクごとの割引率で販売する その1

年末は、再び年明けのEC-CUBEの案件に備えて、色々いじくりテスト。

大きなところで、3つのカスタムテストをしてみました。

1個目は、EC-CUBEの管理画面で、お問い合わせの履歴管理をし、そこからお問い合わせへの返信を行う、というもの。2個目は、商品一覧のテンプレートをカテゴリーごとに別のデザインでもてるようにカスタム。(そのうち詳細ページでも同様のことをやって見ようと思う。)もうひとつは、表題の通り。会員ランクを作って、会員のランクごとに、割引率を定め、特別価格で販売するというもの。

3つ目、結構面倒だった。なにって、、、仕組みとプログラムルートをたどっていくのが!!!オイッ!(何への怒り!?)

(--;)

何とかできたので、久しぶりすぎるブログのネタとして、とりあえず、晒します。
どっか、間違ってたら、指摘して(ついでに直して;)ください。。。

とりあえず、ぐだっとサンプルの仕様を書きます。

主な仕様ですが、会員ランクをまずは、5段階(ランク1~ランク5)とし、それぞれ、通常販売価格(会員以外の一般の人の価格)の10%割引から50%割引まで、割り引くことにします。
会員ランクの数と割引率は、管理画面のマスタデータ管理から追加や変更ができることにして、ランクごとの割引率は一律、とします。(ということで、別にランクは最初1つでもいいんだけど、サンプルなので、とりあえず5つ作る)

割引率が関係するので、お客さんが勝手にランクを登録したらマズい。
ので、お客さんが会員登録したときは、デフォルトで、会員ランクを1とします。つまり、非会員、ランク1~ランク5までの実質6段階の割引率設定があるわけです。
そして、管理画面で、顧客データを検索して、個別編集で、顧客情報の会員ランクを変更して、ランクを変えます。(例えば、優良顧客のみ、年会費をもらって高割引率で販売するようにしたり、高額購入者のみ顧客管理で検索してランクを変えて高割引率で販売したり、そういうことを想定しています。お金が絡むので、自動でランクを変えるようにはしません。もし、そういうことしたい人は、がんばってください。そして、ソースを晒してください。お願いします;)
あとは、メルマガ送信の顧客検索でも、会員ランクごとにメルマガを送りたいときもあるので、ここにもランクでの顧客情報検索を追加しておくことにします。そして、顧客情報CSVにも出力項目として追加しますね。
と、まあ、表面での仕様はこんな感じです。

さて、ここで、システム的な仕様ですが、ランクの追加・削除や割引率は、当然管理者が時々変えたくなるかも知れない項目なので、マスターデータで管理したいんですが、”mtb_”のテーブルはmtb_constants以外カラムが全部3つなんですね。で、会員ランクでは、id、名前,rank,それから割引率の4つ使いたいんですけど、それを作って、マスターデータ管理で編集しようとすると、さらに色々基幹の部分を触らないと行けなさそうで、システムのアップデートのときに、とっても、とっても、大変そう・・・
だから、ちょっと、気持ちわるいっていうか、マスターデータの編集のときに面倒さが残るけど、今回は、会員ランク用のmtb_customer_rankテーブルと割引率用のmtb_customer_discountテーブルの2つを作りました。でも、別にやり方次第で、1つのテーブル追加だけでも全然対応できると思います。
例えば、ランクは、mtb_のrankを共用利用して、使えばいいわけです。ソノへんは、適宜都合のいいようにしてチョウダイ。

まあ、ちょっとまだ表面的なこと(例えば、カートの中で割引率○○%です、みたいな表記出すとか)が、まだですが、そういうのは、テンプレの修正ですぐできるので、後でやります。

これで、下記のような最終動作となります。
まず、管理画面のマスターデータ管理から、mtb_customer_rankの編集で、会員のランクを必要な数だけ追加・削除します。そして、同じくマスターデータのmtb_customer_discountで、そのランクに応じた割引率を設定します。ランクの数は2つのテーブルであわして置いてくださいね。
ここまでが、管理者側の前準備です。
そして、実際にユーザーが、会員登録をしてくれた後、管理者は、適宜その会員に適用したいランクを管理画面の顧客管理から変更して登録します。
すると、その後、会員の買い物時には、ショッピングカートで、購入した商品に、その割引が適用されます。また、注文の追加や変更で、管理画面の受注管理から、顧客の購入情報を修正したときも、変更した割引率が適用されます。
注意する点は、顧客情報を編集した時点およびユーザーがログインした時点の会員ランクが適用されるということです。ですので、以前の購入情報を修正する場合、その間に会員ランクが変更されていれば、更新は新しいランクで行われますし、会員ランクの変更後は、再ログインしてもらうことで新しいランクでの買い物ができる、ということです。

って、長くなりだしましたので、早速本題の作業を開始します。
一応、ですが、そこそこ複雑な作業も含みます。また、備忘録として、EC-CUBEの基本の動作とか触り方をわかっている方向きに書いてますので、本当に初心者なんです~、という方には向きません。
(私のスキルもそこまで達者ではないので、)エラーなどのサポートも基本的にできません。
それでも良い方のみ覚悟して実装してくださいね。

この作業、結構長いので、途中でエントリー分けます。

【DBに追加するテーブル】
・mtb_customer_rank(3カラム)
・mtb_customer_discount(3カラム)

【触るファイル】
今回は管理機能メインになるので、テストだし、面倒だから、class_exは使いませんでした。
気になる方は、使ってください。
・/data/class/SC_CustomerList.php
・/data/class/helper/SC_Helper_DB.php
・/data/class/helper/SC_Helper_CSV.php
・/data/class/page/admin/customer/SC_Page_Admin_Customer.php
・/data/class/page/admin/customer/SC_Page_Admin_Customer_Edit.php
・/data/Smarty/templates/default/admin/customer/index.tpl
・/data/Smarty/templates/default/admin/customer/edit.tpl
・/data/Smarty/templates/default/admin/customer/edit_confirm.tpl
・/data/Smarty/templates/default/admin/mail/index.tpl
・/data/Smarty/templates/default/admin/mail/query.tpl

【ステップ1】
データベースにテーブルを2つ追加します。

・mtb_customer_rank (※全てnotnull=空白非許可)

id 1 ※smallint(6)/ユニークキーで作成
name ランク1 ※textで作成
rank 1 ※smallint(6)で作成

作成後、セルを追加で4つ作り、ランク1~ランク5までの値を登録する。

・mtb_customer_disucount (※全てnotnull=空白非許可)

id 1 ※smallint(6)/ユニークキーで作成
name 0.9 ※textで作成
rank 1 ※smallint(6)で作成

nameの数字は、1を100%価格として、割引後の掛け率。(0.9=10%offということ)

作成後、セルを追加で4つ作り、0.9/0.8/0.7/0.6/0.5の値を登録する。(それぞれランク1~5の割引掛け率に相当する)

さらに、もともとある、dtb_customerテーブルに、customer_rankというカラムをsmallint(6)で追加します。
ここへ、顧客ごとのランクを書き込んでいく仕様にします。
最後に、CSVの出力用に、dtb_csvテーブルの最後に、customer_rankの行を追加し、ID=85の更新日を参考に、rankがその次の値になるように入力します。

できました?

続きのエントリーはこちらです。↓

https://bton.papalabs.net/?p=1301

https://bton.papalabs.net/?p=1312