1 # -*- coding: utf-8 -*-
4 class CartController < BaseController
5 include CartControllerExtend
7 ssl_required :temporary_shipping, :shipping, :delivery, :delivery2, :purchase, :purchase2, :purchase_confirm, :confirm, :complete, :before_finish, :finish, :select_delivery_time, :select_delivery_time_with_delivery_trader_id_ajax
9 before_filter :cart_check, :only => [:temporary_shipping,:shipping, :purchase,:purchase2, :confirm, :complete, :delivery, :delivery2]
10 before_filter :login_divaricate ,:only =>[:purchase,:purchase2,:confirm, :complete, :delivery, :delivery2]
11 before_filter :login_check, :only => [:shipping]
12 before_filter :force_post, :only => [:delivery, :purchase,:purchase2,:confirm, :complete]
13 after_filter :save_carts
14 before_filter :verify_session_token, :except => :select_delivery_time
17 DENA_AFFILIATE_URL = 'http://smaf.jp/req.cgi'
19 # カートの中を見る。Loginの可否、カート内容の有無で動的に変動。カート操作全般はここから行う。
21 unless @carts.all?(&:valid?)
22 flash.now[:error] = cart_errors(@carts)
24 @cart_point = total_points
26 @recommend_for_you = Recommend.recommend_get(@carts.last.product_id, Recommend::TYPE_VIEW)
34 :value => Fixnum[デフォルト値: 1]
35 :product_id => Fixnum[必須]
36 :classcategory_id1 => Fixnum[必須ではない]
37 :classcategory_id2 => Fixnum[必要ではない]
40 カート内の商品の個数を [value]分加算する
41 規格分類1または規格分類2が指定された場合は、指定された規格分類の個数を加算する
42 規格分類1と規格分類2が指定された場合は、両方の規格分類を持つ商品の個数を加算する
43 規格分類が指定されない場合は、商品の個数を加算する
47 # TODO キーはインデックスにしたい: そのほうがユーザ視点で自然なので。
48 value = params[:value] || 1
49 cart = find_cart(:product_style_id => params[:id].to_i)
50 if cart.nil? || cart.product_style.nil?
51 redirect_to :action => :show
54 new_quantity = cart.quantity + value
55 cart.quantity = cart.product_style.available?(new_quantity)
56 if cart.quantity < new_quantity
57 flash[:notice] = '購入できる上限を超えています'
59 redirect_to :action => 'show'
66 :value => Fixnum[デフォルト値: 1]
67 :product_id => Fixnum[必須]
70 カート内の商品の個数を [value]分減算する
71 減算した結果、商品の個数が 0 以下となる場合は 1 個にする
74 value = params[:value] || 1
75 cart = find_cart(:product_style_id => params[:id].to_i)
76 if cart.nil? || cart.product_style.nil?
77 redirect_to :action => :show
80 new_quantity = cart.quantity - value
81 if new_quantity <= 1 then
84 cart.quantity = new_quantity
85 redirect_to :action => 'show'
92 :product_style_id => Fixnum[必須]
99 cart = find_cart(:product_style_id => params[:id].to_i)
101 redirect_to :action => :show
104 @carts.reject!{|i|i==cart}
106 cart.destroy unless cart.new_record?
107 redirect_to :action => 'show'
112 unless @carts.all?(&:valid?)
113 redirect_to :action => :show
116 cookies[:back_from_deliv] = {
117 :value => url_for({:controller => 'cart', :action => 'shipping'}),
118 :expires => 30.minutes.from_now
121 @address_size = DeliveryAddress.count(:conditions => ["customer_id =?", @login_customer.id])
122 @addresses = DeliveryAddress.find(:all, :conditions => ["customer_id =?", @login_customer.id], :include => :customer)
123 basic_address = @login_customer.basic_address
124 @addresses.unshift(basic_address) if basic_address
129 def temporary_shipping
130 unless @carts.all?(&:valid?)
131 redirect_to :action => :show
134 @temporary_customer = Customer.new(params[:temporary_customer])
135 @optional_address = DeliveryAddress.new(params[:optional_address])
137 if params[:back] == "1"
138 logger.debug params[:order_deliveries]["1"]
139 convert(params[:order_deliveries].first[1])
144 cookies.delete :back_from_deliv if cookies[:back_from_deliv]
149 if params[:address_select].to_i.zero?
151 @delivery_address = @login_customer.basic_address
154 @delivery_address = DeliveryAddress.find_by_id_and_customer_id(params[:address_select], @login_customer.id)
156 elsif @not_login_customer
158 @temporary_customer = Customer.new(params[:temporary_customer])
159 @temporary_customer.from_cart = true
162 #if params[:address_enable].nil?
163 @optional_address = DeliveryAddress.new(params[:optional_address])
167 if params[:back] == "1"
168 convert(params[:order_deliveries].first[1])
172 @temporary_customer.activate = Customer::HIKAIIN
173 if !@temporary_customer.valid? or
174 (params[:address_enable].nil? and !@optional_address.valid?)
176 render :action => "temporary_shipping"
181 if params[:address_enable].nil?
182 @delivery_address = @optional_address
184 @delivery_address = @temporary_customer.basic_address
188 # 住所を取得できないと、この先困るので、どこかに飛ばす
189 return redirect_to(:action => 'show') unless @delivery_address
191 @order_deliveries = Hash.new
192 unless params[:order_deliveries].nil?
193 params[:order_deliveries].each do |key, order_delivery|
194 @order_deliveries[key] = OrderDelivery.new(order_delivery)
197 if @order_deliveries.empty?
198 @carts.map(&:product_style).map(&:product).map(&:retailer).each do |retailer|
199 od = OrderDelivery.new
200 od.set_delivery_address(@delivery_address)
201 @order_deliveries[retailer.id] = od
204 @delivery_traders = Hash.new
205 @carts.map(&:product_style).map(&:product).map(&:retailer).each do |retailer|
206 @delivery_traders[retailer.id] = select_delivery_trader_with_retailer_id(retailer.id)
208 if @not_login_customer
209 @order_deliveries.each do |key, order_delivery|
210 order_delivery.set_customer(@temporary_customer)
213 render :action => 'delivery'
218 @order_deliveries = Hash.new
219 unless params[:order_deliveries].nil?
220 params[:order_deliveries].each do |key, order_delivery|
221 @order_deliveries[key] = OrderDelivery.new(order_delivery)
226 @delivery_time_options = Hash.new
227 @order_deliveries.each do |retailer_id, od|
228 delivery_trader_id = od.delivery_trader_id
229 option = select_delivery_time_with_delivery_trader_id(delivery_trader_id)
230 @delivery_time_options[retailer_id] = option
232 render :action => 'delivery2'
237 @order_deliveries = Hash.new
238 unless params[:order_deliveries].nil?
239 params[:order_deliveries].each do |key, order_delivery|
240 @order_deliveries[key] = OrderDelivery.new(order_delivery)
246 if params[:back] == "1"
247 @payment_id = @order_deliveries.first[1].payment_id
250 render :action => 'purchase'
256 @order_delivery = OrderDelivery.new(params[:order_delivery])
257 unless @order_delivery.valid?
258 if params[:point_check] == "true"
261 render :action => 'purchase'
266 if params[:point_check] == "true"
268 use_point = @order_delivery.use_point.to_i
270 flash.now[:error] = '使用ポイントをご入力ください。 '
271 render :action => 'purchase'
275 if use_point > @cart_price
276 flash.now[:error] = 'ご利用ポイントがご購入金額を超えています。'
277 render :action => 'purchase'
280 if use_point > @login_customer.point.to_i
281 flash.now[:error] = 'ご利用ポイントが所持ポイントを超えています。'
282 render :action => 'purchase'
287 @order_delivery.attributes = {:use_point => 0}
292 @order_delivery.target_columns = params[:order_delivery].keys.map(&:to_s)
295 def select_delivery_time_with_delivery_trader_id_ajax
296 delivery_trader_id = params[:delivery_trader_id]
297 @options = select_delivery_time_with_delivery_trader_id(delivery_trader_id)
298 render :layout => false unless request.mobile?
303 def select_delivery_time
304 h = params[:order_delivery] || params
305 payment_id = h[:payment_id]
306 @selected = h[:delivery_time_id]
307 delivery_times = DeliveryTime.find(
308 :all, :conditions => ["payments.id=? and delivery_times.name <> ''", payment_id],
309 :include => [:delivery_trader=>:payments], :order => 'delivery_times.position')
310 @options = [['指定なし', nil]]
311 @options.concat(delivery_times.map do |dt|
314 render :layout => false unless request.mobile?
319 init_order_deliveries
320 @order_deliveries.each do |key, od|
322 render :action => 'purchase'
329 @order_deliveries.each do |retailer_id, od|
330 if !params[:points].nil? && !params[:points][retailer_id].nil? && params[:points][retailer_id][:point_check] == "true"
331 use_point = od.use_point.to_i
333 flash.now[:error] = '使用ポイントをご入力ください。'
334 render :action => 'purchase'
337 if use_point > @cart_price_map[retailer_id.to_i].to_i
338 flash.now[:error] = 'ご利用ポイントがご購入金額を超えています。'
339 render :action => 'purchase'
342 @all_use_point = @all_use_point + use_point
346 if @all_use_point > @login_customer.point.to_i
347 flash.now[:error] = 'ご利用ポイントが所持ポイントを超えています。'
348 render :action => 'purchase'
352 od.attributes = {:add_point => total_points_each_cart(@carts_map[retailer_id.to_i])}
354 @cart_point = total_points
355 @point_after_operation = @login_customer.point.to_i - @all_use_point + @cart_point
356 session[:point_after_operation] = @point_after_operation
360 @order_deliveries.each do |retailer_id, od |
363 @payment_total = @payment_total + od.payment_total
367 render :action => 'confirm'
372 unless @carts.all?(&:valid?)
373 redirect_to :action => :show
376 @login_customer.point = session[:point_after_operation] if @login_customer
378 @order_deliveries = Hash.new
379 @order_details = Hash.new
381 params[:order_deliveries].each do |key, _od|
383 if @not_login_customer
386 order = @login_customer.orders.build
388 order.retailer_id = key.to_i
389 order.received_at = DateTime.now
390 od = order.order_deliveries.build(_od)
391 od.set_customer(@login_customer) if @login_customer
392 od.status = OrderDelivery::JUTYUU
394 @order_deliveries[key] = od
395 cart = @carts_map[key.to_i]
396 @order_details[key] = od.details_build_from_carts(cart)
399 @ids << @order_details[key].map{|o_d| o_d.product_style.product_id}
402 @order_deliveries.each do |key, od|
403 unless od.valid? and @order_details[key].all?(&:valid?)
404 render :action => 'purchase'
409 if @order_deliveries.empty? or @order_details.empty?
410 render :action => 'purchase'
414 # paymentロジックをプラグイン化するため、予めセッションに保存しておき画面遷移で引き回さないようにする
415 save_transaction_items_before_payment
416 payment_id = @order_deliveries.first[1].payment_id
417 payment = Payment.find(payment_id)
418 #p "plugin_id: " + payment.payment_plugin_id.to_s
419 payment_plugin = payment.get_plugin_instance
420 #p payment_plugin.name
421 self.send payment_plugin.next_step(current_method_symbol)
424 restore_transaction_items_after_payment
428 flash.now[:error] = '失敗しました'
429 logger.error(e.message)
430 e.backtrace.each{|s|logger.error(s)}
431 redirect_to :action => 'show'
434 redirect_to :action => :finish, :ids => @ids
440 unless flash[:completed]
441 render :template => 'cart/405', :status => :method_not_allowed
444 session[:point_after_operation] = nil
445 session[:transaction_items] = nil
446 @recommend_buys = Recommend.recommend_get(params[:ids][0], Recommend::TYPE_BUY)
447 @shop = Shop.find(:first)
448 render :action => 'complete'
455 :product_style_id => Fixnum[必須ではない]
456 :product_id => Fixnum[必須]
457 :style_category_id1 => Fixnum[必須ではない]
458 :style_id2 => Fixnum[必須ではない]
462 セッションに保持しているカートに、商品を追加する
463 セッションにカートを保持していない場合は、カートそのものを新たに所持する
464 既にカートに同じ商品がある場合は、カート内の商品の個数を [size] 分だけ加算する
465 [size] が購入可能な上限数を超過する場合、購入可能な上限数までカートへ入れ、
466 購入制限により購入できない、とする旨のメッセージを返す。
467 購入できない商品の場合は、カートに入れない
470 @add_product = CartAddProductForm.new(params)
471 unless @add_product.valid?
472 flash[:cart_add_product] = @add_product.errors.full_messages
473 if @add_product.product_id
474 flash['error_%d' % @add_product.product_id] = flash[:cart_add_product]
476 request.env['HTTP_REFERER'] ||= url_for(:action=>:show)
482 if params[:product_style_id]
483 ProductStyle.find_by_id(params[:product_style_id])
485 ProductStyle.find_by_product_id_and_style_category_id1_and_style_category_id2(params[:product_id], params[:style_category_id1], params[:style_category_id2])
488 if product_style.nil?
489 flash[:cart_add_product] = "ご指定の商品は購入できません。"
490 request.env['HTTP_REFERER'] ||= url_for(:action=>:show)
495 cart = find_cart(:product_style_id => product_style.id)
497 if @carts.size >= CARTS_MAX_SIZE
498 flash[:cart_add_product] = '一度に購入できる商品は ' + "#{CARTS_MAX_SIZE}" + '種類までです。'
499 redirect_to :action => 'show'
502 cart = Cart.new(:product_style => product_style,
503 :customer => @login_customer,
508 unless params[:campaign_id].blank?
509 cart.campaign_id = params[:campaign_id]
512 size = [params[:size].to_i, 1].max
513 # 購入可能であれば、カートに商品を追加する
514 insert_size = product_style.available?(cart.quantity + size)
515 incremental = insert_size - cart.quantity # 増分
516 product_name = product_style.full_name
517 if insert_size.to_i <= 0
518 # 購入可能な件数が 0 より小さい場合はカートを追加しない
520 flash[:cart_add_product] = "「#{product_name}」は購入できません。"
521 elsif incremental < size
523 flash[:cart_add_product] = "「#{product_name}」は販売制限しております。一度にこれ以上の購入はできません。"
525 cart.quantity = insert_size
526 session[:cart_last_product_id] = product_style.product_id
527 redirect_to :action => 'show'
532 def save_before_finish
534 @carts.each do | cart |
536 ProductAccessLog.create(:product_id => cart.product_style.product_id,
537 :session_id => session.session_id,
538 :customer_id => @login_customer && @login_customer.id,
539 :docomo_flg => request.mobile == Jpmobile::Mobile::Docomo,
540 :ident => request.mobile.ident,
541 :complete_flg => true)
543 product_style = ProductStyle.find(cart.product_style_id, :lock=>true)
544 product_style.order(cart.quantity)
548 cart.campaign_id and process_campaign(cart, @login_customer)
553 @login_customer.carts.delete_all
554 @login_customer.save!
558 @orders.each do |key, order|
560 order_ids[key] = order.id
561 Notifier::deliver_buying_complete(order)
563 flash[:completed] = true
564 flash[:order_ids] = order_ids
565 flash[:googleanalytics_ecs] = add_googleanalytics_ecs(@orders, @order_deliveries, @order_details)
575 現在、カート内にある商品で購入時に加算されるポイントの合計値を返す。
579 @carts.inject(0) do | result, cart |
581 point_rate_product = cart.product.point_granted_rate
582 point_rate_shop = Shop.find(:first).point_granted_rate
583 point_granted_rate = 0
584 unless point_rate_product.blank?
585 point_granted_rate = point_rate_product
587 unless point_rate_shop.blank?
588 point_granted_rate = point_rate_shop
591 result + cart.price * point_granted_rate / 100 * cart.quantity
595 def total_points_each_cart(carts)
596 carts.inject(0) do | result, cart |
598 point_rate_product = cart.product.point_granted_rate
599 point_rate_shop = Shop.find(:first).point_granted_rate
600 point_granted_rate = 0
601 unless point_rate_product.blank?
602 point_granted_rate = point_rate_product
604 unless point_rate_shop.blank?
605 point_granted_rate = point_rate_shop
608 result + cart.price * point_granted_rate / 100 * cart.quantity
612 # 購入時にログイン有無を確認してrenderするフィルタ
614 if @login_customer.nil?
615 if params[:temporary_customer_flag] && params[:temporary_customer_flag] == "1"
616 @not_login_customer = true
619 unless @not_login_customer
620 unless session[:customer_id]
621 session[:return_to] = params if params
622 redirect_to(:controller => 'accounts', :action => 'login')
627 # @carts から条件に合うものを探す
628 # ex) find_cart(:product_style_id => 1)
629 def find_cart(conditions)
630 @carts.detect do | cart |
631 conditions.all? do | key, value |
639 if request.method != :post
640 render :template => 'cart/405', :status => :method_not_allowed
647 flash.now[:notice] = 'カートが空です'
648 redirect_to(:action => 'show')
652 def cart_errors(carts)
653 errors = carts.enum_for(:each_with_index).reject do |c,_|
656 c.errors.full_messages.map do |message|
658 name = c.product_style.full_name
660 name = '%d 番目の商品' % (i+1)
662 '%s: %s' % [name, message]
664 end.flatten.uniq.join("\n")
667 def init_order_deliveries_for_complete
668 @order_deliveries = Hash.new
669 params[:order_deliveries].each do |key, order_delivery|
670 @order_deliveries[key] = OrderDelivery.new(order_delivery)
671 @order_deliveries[key].set_customer(@login_customer) if @login_customer
673 @order_details_map = Hash.new
674 @order_deliveries.each do |key, order_delivery|
675 cart = @carts_map[key.to_i]
676 @order_details_map[key] = order_delivery.details_build_from_carts(cart)
680 def init_order_deliveries
681 @order_deliveries = Hash.new
682 params[:order_deliveries].each do |key, order_delivery|
683 @order_deliveries[key] = OrderDelivery.new(order_delivery)
684 @order_deliveries[key].set_customer(@login_customer) if @login_customer
685 @order_deliveries[key].payment_id = params[:order_delivery][:payment_id]
687 @order_details_map = Hash.new
688 @order_deliveries.each do |key, order_delivery|
689 cart = @carts_map[key.to_i]
690 @order_details_map[key] = order_delivery.details_build_from_carts(cart)
695 def init_order_delivery
696 @order_delivery = OrderDelivery.new(params[:order_delivery])
697 @order_delivery.set_customer(@login_customer) if @login_customer
698 @order_details = @order_delivery.details_build_from_carts(@carts)
701 def process_campaign(cart, customer)
702 cp = Campaign.find_by_id(cart.campaign_id)
703 return if cp.product_id != cart.product_style.product_id
704 return if cp.duplicated?(customer)
705 cp.customers << customer
706 cp.application_count ||= 0
707 cp.application_count += 1
711 # purchase だけで必要だが、他のアクションから render されることもあるのでいっそ全部で読み込む
713 @card_price or return false
719 order_delivery = OrderDelivery.new(params)
721 @temporary_customer.family_name = order_delivery.family_name
722 @temporary_customer.first_name = order_delivery.first_name
723 @temporary_customer.family_name_kana = order_delivery.family_name_kana
724 @temporary_customer.first_name_kana = order_delivery.first_name_kana
725 @temporary_customer.tel01 = order_delivery.tel01
726 @temporary_customer.tel02 = order_delivery.tel02
727 @temporary_customer.tel03 = order_delivery.tel03
728 @temporary_customer.fax01 = order_delivery.fax01
729 @temporary_customer.fax02 = order_delivery.fax02
730 @temporary_customer.fax03 = order_delivery.fax03
731 @temporary_customer.zipcode01 = order_delivery.zipcode01
732 @temporary_customer.zipcode02 = order_delivery.zipcode02
733 @temporary_customer.prefecture_id = order_delivery.prefecture_id
734 @temporary_customer.address_city = order_delivery.address_city
735 @temporary_customer.address_detail = order_delivery.address_detail
736 @temporary_customer.email = order_delivery.email
737 @temporary_customer.email_confirm = order_delivery.email
738 @temporary_customer.sex = order_delivery.sex
739 @temporary_customer.birthday = order_delivery.birthday
740 @temporary_customer.occupation_id = order_delivery.occupation_id
743 @optional_address.family_name = order_delivery.deliv_family_name
744 @optional_address.first_name = order_delivery.deliv_first_name
745 @optional_address.family_name_kana = order_delivery.deliv_family_name_kana
746 @optional_address.first_name_kana = order_delivery.deliv_first_name_kana
747 @optional_address.tel01 = order_delivery.deliv_tel01
748 @optional_address.tel02 = order_delivery.deliv_tel02
749 @optional_address.tel03 = order_delivery.deliv_tel03
750 @optional_address.zipcode01 = order_delivery.deliv_zipcode01
751 @optional_address.zipcode02 = order_delivery.deliv_zipcode02
752 @optional_address.prefecture_id = order_delivery.deliv_pref_id
753 @optional_address.address_city = order_delivery.deliv_address_city
754 @optional_address.address_detail = order_delivery.deliv_address_detail
757 def add_googleanalytics_ecs(orders, deliveries, details_map)
758 googleanalytics_ecs = Array.new
759 orders.each do |key, order|
760 delivery = deliveries[key]
761 details = details_map[key]
762 googleanalytics_ecs << add_googleanalytics_ec(order, delivery, details)
764 return googleanalytics_ecs
767 def add_googleanalytics_ec(order, delivery, details)
768 ecommerce = GoogleAnalyticsEcommerce.new
769 trans = GoogleAnalyticsTrans.new
770 trans.order_id = order.code
772 trans.city = delivery.address_city
773 trans.country = "japan"
774 trans.state = delivery.prefecture.name
775 trans.shipping = delivery.deliv_fee.to_s
777 trans.total = delivery.total.to_s
779 details.each do | detail |
780 item = GoogleAnalyticsItem.new
781 item.order_id = order.code
782 item.category = detail.product_category.name
783 item.product_name = detail.product_name
784 item.price = detail.price.to_s
785 item.quantity = detail.quantity.to_s
786 item.sku = detail.product_style.manufacturer_id
787 ecommerce.add_item(item)
790 ecommerce.trans = trans
792 #flash[:googleanalytics_ec] = ecommerce
796 def select_delivery_trader_with_retailer_id(retailer_id)
797 return DeliveryTrader.find(:all, :conditions => ["retailer_id = ?", retailer_id])
800 def select_delivery_time_with_delivery_trader_id(delivery_trader_id)
801 delivery_times = DeliveryTime.find(:all, :conditions => ["delivery_trader_id = ? and name <> ''", delivery_trader_id], :order => 'position')
802 options = [['指定なし', nil]]
803 options.concat(delivery_times.map do |dt|
809 def current_method_symbol
810 caller.first.scan(/`(.*)'/).to_s.intern
813 def save_transaction_items_before_payment
814 transaction_items = Hash.new
815 transaction_items[:carts] = @carts
816 transaction_items[:login_customer] = @login_customer
817 transaction_items[:orders] = @orders
818 transaction_items[:order_deliveries] = @order_deliveries
819 transaction_items[:order_details] = @order_details
820 transaction_items[:ids] = @ids
821 transaction_items[:not_login_customer] = @not_login_customer
822 session[:transaction_items] = transaction_items
825 def restore_transaction_items_after_payment
826 transaction_items = session[:transaction_items]
827 @carts = transaction_items[:carts]
828 @login_customer = transaction_items[:login_customer]
829 @orders = transaction_items[:orders]
830 @order_deliveries = transaction_items[:order_deliveries]
831 @order_details = transaction_items[:order_details]
832 @ids = transaction_items[:ids]
833 @not_login_customer = transaction_items[:not_login_customer]