boom
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
class Admin::DigitalsController < Admin::BaseController
|
||||
|
||||
resource_controller
|
||||
|
||||
index.before do
|
||||
@product = Product.find_by_permalink(params[:product_id])
|
||||
end
|
||||
|
||||
create.wants.html { redirect_to admin_product_digitals_url(@product) }
|
||||
destroy.wants.html { redirect_to admin_product_digitals_url(@product) }
|
||||
|
||||
end
|
||||
@@ -0,0 +1,16 @@
|
||||
class DigitalsController < Spree::BaseController
|
||||
|
||||
ssl_required :show
|
||||
|
||||
def show
|
||||
link = DigitalLink.find_by_secret(params[:secret])
|
||||
if link.present? and link.digital.attachment.present?
|
||||
attachment = link.digital.attachment
|
||||
if link.authorize! and File.file?(attachment.path)
|
||||
send_file attachment.path :filename => attachment.original_filename, :type => attachment.content_type and return
|
||||
end
|
||||
end
|
||||
render :unauthorized
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
class Digital < ActiveRecord::Base
|
||||
|
||||
belongs_to :variant
|
||||
has_many :digital_links, :dependent => :destroy
|
||||
|
||||
has_attached_file :attachment, :path => ":rails_root/private/digitals/:id/:basename.:extension"
|
||||
|
||||
# TODO: Limit the attachment to one single file. Paperclip supports many by default :/
|
||||
|
||||
end
|
||||
@@ -0,0 +1,27 @@
|
||||
class DigitalLink < ActiveRecord::Base
|
||||
|
||||
belongs_to :digital
|
||||
belongs_to :line_item
|
||||
|
||||
before_validation :set_defaults, :on => :create
|
||||
|
||||
# Can this link stil be used? It is valid if it's less than 24 hours old and was not accessed more than 3 times
|
||||
def authorizable?
|
||||
self.created_at > 1.day.ago and self.access_counter < 3
|
||||
end
|
||||
|
||||
# This method should be called when a download is initiated.
|
||||
# It returns +true+ or +false+ depending on whether the authorization is granted.
|
||||
def authorize!
|
||||
authorizable? && increment!(:access_counter) ? true : false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Populating the secret automatically and zero'ing the access_counter (otherwise it might turn out to be NULL)
|
||||
def set_defaults
|
||||
self.secret = SecureRandom.hex(15)
|
||||
self.access_counter = 0
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,22 @@
|
||||
LineItem.class_eval do
|
||||
|
||||
has_many :digital_links
|
||||
|
||||
after_save :create_digital_links, :if => :digital?
|
||||
|
||||
# Is this item digital?
|
||||
def digital?
|
||||
variant.digital?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Create the download link for this item if it is digital.
|
||||
def create_digital_links
|
||||
digital_links.delete_all
|
||||
self.quantity.times do
|
||||
digital_links.create!(:digital => variant.digital)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
Order.class_eval do
|
||||
|
||||
# Are all products/variants of this Order to be downloaded by the customer?
|
||||
def digital?
|
||||
line_items.map { |item| return false unless item.digital? }
|
||||
true
|
||||
end
|
||||
|
||||
# Determine which method to use for shipping of digital products.
|
||||
def digital_shipping_method
|
||||
rates = rate_hash
|
||||
# If there is a shipping method has "Download" in its name then we take that one.
|
||||
rates.each { |rate| return rate if rate[:name].downcase.include?('download') }
|
||||
# Other than that, we take the first one that we find that doesn't cost anything.
|
||||
rates.each { |rate| return rate if rate[:cost] == 0 }
|
||||
# Well, at this point we have a problem. No shipping method is cost-free or called "download".
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
Variant.class_eval do
|
||||
|
||||
has_one :digital, :dependent => :destroy
|
||||
after_save :destroy_digital, :if => :deleted?
|
||||
|
||||
# Is this variant to be downloaded by the customer?
|
||||
def digital?
|
||||
digital.present?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Spree never deleted Digitals, that's why ":dependent => :destroy" won't work on Digital.
|
||||
# We need to delete the Digital manually here as soon as the Variant is nullified.
|
||||
# Otherwise you'll have orphan Digitals (and their attached files!) associated with unused Variants.
|
||||
def destroy_digital
|
||||
digital.destroy
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
<% if digital.attachment_file_name.present? %>
|
||||
<%= digital.attachment_file_name %> (<%= number_to_human_size(digital.attachment_file_size) %>)
|
||||
<% else %>
|
||||
<%=t 'broken_file' %>
|
||||
<% end %>
|
||||
@@ -0,0 +1,35 @@
|
||||
<div class="yui-g">
|
||||
<div class="yui-u first">
|
||||
<%= form_for(:digital, :url => { :controller => 'digitals', :action => 'create' }, :html => { :multipart => true }) do |f| %>
|
||||
<fieldset>
|
||||
<legend><%= Variant.human_name %> "<%= variant.options_text %>"</legend>
|
||||
|
||||
<%= f.field_container :current_file do %>
|
||||
<strong><%=t 'current_file' %>:</strong><br/>
|
||||
<% if variant.digital? %>
|
||||
<%= render variant.digital %><%= %>
|
||||
<% else %>
|
||||
<%=t 'none' %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<p class="form-buttons">
|
||||
<% if variant.digital? %>
|
||||
<%= link_to t("delete_file"), admin_product_digital_url(:id => variant.digital.id), :confirm => t('delete_file_cofirmation', :filename => variant.digital.attachment_file_name), :method => :delete %>
|
||||
<% else %>
|
||||
|
||||
<%= f.field_container :file do %>
|
||||
<%= f.label :file, t("new_file") %> <span class="required">*</span><br/>
|
||||
<%= f.file_field :attachment %>
|
||||
<% end %>
|
||||
|
||||
<%= hidden_field_tag 'digital[variant_id]', variant.id %>
|
||||
|
||||
<%= button t("upload") %>
|
||||
<% end %>
|
||||
</p>
|
||||
|
||||
</fieldset>
|
||||
<% end %>
|
||||
</div>
|
||||
</div><br/>
|
||||
@@ -0,0 +1,20 @@
|
||||
<%= render :partial => 'admin/shared/product_sub_menu' %>
|
||||
<%= render :partial => 'admin/shared/product_tabs', :locals => {:current => "Digital Versions"} %>
|
||||
|
||||
<% if @product.has_variants? %>
|
||||
|
||||
<% for variant in @product.variants do %>
|
||||
<%= render 'form', :variant => variant %>
|
||||
<% end %>
|
||||
|
||||
<% else %>
|
||||
This product has no variants.
|
||||
|
||||
<% if @product.master.digital? %>
|
||||
A digital version of this product currently exists:
|
||||
<%= render @product.master.digital %>
|
||||
<% end %>
|
||||
|
||||
<%= render 'form', :variant => @product.master %>
|
||||
|
||||
<% end %>
|
||||
@@ -0,0 +1,5 @@
|
||||
<%#
|
||||
This is basically a switch that will render the appropriate "delivery choice" partial.
|
||||
When there are no physical items at all, there should be no different shipping methods to choose.
|
||||
%>
|
||||
<%= render @order.digital? && @order.digital_shipping_method.present? ? 'delivery_digital' : 'delivery_original' %>
|
||||
@@ -0,0 +1,12 @@
|
||||
<fieldset id='shipping_method'>
|
||||
<legend><%= t("shipping_method") %></legend>
|
||||
|
||||
<%= radio_button :order, :shipping_method_id, @order.digital_shipping_method[:id] %>
|
||||
<%==t 'digital_shipping', :email => current_user.email %> (<%= number_to_currency @order.digital_shipping_method[:cost] %>)
|
||||
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="form-buttons">
|
||||
<input type="submit" class="continue button primary" value="<%=t("save_and_continue") %>"/>
|
||||
</div>
|
||||
@@ -0,0 +1,32 @@
|
||||
<%#
|
||||
NOTE: The code below is an exact duplication of `spree_core/views/checkout/_delivery.html.erb´
|
||||
We overwrote the original so we retain access to it by cloning it here.
|
||||
Feel free to update the code below according to the original if needed!
|
||||
%>
|
||||
|
||||
<fieldset id='shipping_method'>
|
||||
<legend><%= t("shipping_method") %></legend>
|
||||
<div class="inner">
|
||||
<div id="methods">
|
||||
<p class="field radios">
|
||||
<% @order.rate_hash.each do |shipping_method| %>
|
||||
<% next if shipping_method[:id] == @order.digital_shipping_method[:id] %>
|
||||
<label>
|
||||
<%= radio_button(:order, :shipping_method_id, shipping_method[:id]) %>
|
||||
<%= shipping_method[:name] %> <%= number_to_currency shipping_method[:cost] %>
|
||||
</label><br />
|
||||
<% end %>
|
||||
</p>
|
||||
</div>
|
||||
<% if Spree::Config[:shipping_instructions] && @order.rate_hash.present? %>
|
||||
<p id="minstrs">
|
||||
<%= form.label :special_instructions, t("shipping_instructions") %><br />
|
||||
<%= form.text_area :special_instructions, :cols => 40, :rows => 7 %>
|
||||
</p>
|
||||
<% end %>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="form-buttons">
|
||||
<input type="submit" class="continue button primary" value="<%=t("save_and_continue") %>"/>
|
||||
</div>
|
||||
@@ -0,0 +1,36 @@
|
||||
Dear Customer,
|
||||
|
||||
Please review and retain the following order information for your records.
|
||||
|
||||
============================================================
|
||||
Order Summary
|
||||
============================================================
|
||||
<% for item in @order.line_items %>
|
||||
<%= item.variant.sku %> <%=item.variant.product.name%> <%= variant_options(item.variant) %> (<%=item.quantity%>) @ <%= number_to_currency item.price %> = <%= number_to_currency(item.price * item.quantity) %>
|
||||
<% end %>
|
||||
============================================================
|
||||
Subtotal: <%= number_to_currency @order.item_total %>
|
||||
<% @order.adjustments.each do |adjustment| %>
|
||||
<%= "#{adjustment.label}: #{number_to_currency adjustment.amount}"%>
|
||||
<% end %>
|
||||
Order Total: <%= number_to_currency @order.total %>
|
||||
|
||||
============================================================
|
||||
Download links for digital products
|
||||
============================================================
|
||||
|
||||
ATTENTION! Each link will only work a SINGLE TIME!
|
||||
Also, they will only work WITHIN 24 HOURS!
|
||||
|
||||
<% for item in @order.line_items %>
|
||||
<% if item.digital? %>
|
||||
<%= item.variant.name %>:
|
||||
<% for link in item.digital_links %>
|
||||
<%= digital_url :protocol => 'https', :host => "yourdomainxygoeshere.com", :secret => link.secret %>
|
||||
<% end %>
|
||||
|
||||
<% end %>
|
||||
<% end %>
|
||||
============================================================
|
||||
|
||||
Thank you for your business.
|
||||
Reference in New Issue
Block a user