0
@@ -29,612 +29,8 @@ class Order
0
property :shipping_cost, Float, :default => 0.0
0
property :tax, Float, :default => 0.0, :nullable => false
0
- #property t.string :auth_transaction_id"
0
- #property t.integer :shipping_address_id", :default => 0, :null => false
0
- #property t.integer :billing_address_id", :default => 0, :null => false
0
validates_presence_of :order_number
0
- # FIXME: fix validates_uniqueness_of
0
- #validates_uniqueness_of :order_number
0
- # CALLBACKS =================================================================
0
- #before_save :set_product_cost
0
- #before_save :set_promo_code
0
- # Sets product cost based on line items total before a save.
0
- self.product_cost = self.line_items_total
0
- # Modifies the order based on any promotion codes passed in.
0
- # This can add discounts to the order or add items.
0
- # Returns silently and just doesn't add the promo if something
0
- # Find promotion based on code entered
0
- promo = Promotion.first(:code => self.promotion_code)
0
- # No promo code? Not active? No deal...
0
- return if !promo || !promo.is_active?
0
- # Make sure it's valid to add
0
- if promo.minimum_cart_value
0
- return if promo.minimum_cart_value > self.total
0
- logger.info "PROMO MIN CART VALUE PASSED"
0
- # Don't allow more than one promotion?
0
- # This destroys any line items created previously.
0
- self.promotion_line_item.destroy if self.promotion_line_item
0
- # Assign proper promotion ID
0
- self.promotion_id = promo.id
0
- # Add any line items necessary from promotion.
0
- oli = OrderLineItem.new
0
- logger.info "CREATED OLI"
0
- oli.name = promo.description
0
- oli.item_id = promo.item_id
0
- # Figure out how to apply the promotion
0
- case promo.discount_type
0
- oli.unit_price = -promo.discount_amount
0
- oli.unit_price = -(self.total * (promo.discount_amount/100))
0
- item = self.order_line_items.detect { |i| i.item_id == promo.item_id }
0
- if item && item.quantity >= promo.discount_amount.to_i
0
- oli.quantity = item.quantity / promo.discount_amount.to_i
0
- logger.info "ITEM QUANTITY #{oli.quantity}"
0
- self.order_line_items << oli
0
- # CLASS METHODS =============================================================
0
- # Uses order number, first name, last name
0
- def self.search(search_term, count=false, limit_sql=nil)
0
- if (count == true) then
0
- sql = "SELECT COUNT(*) "
0
- sql = "SELECT DISTINCT orders.* "
0
- sql << "JOIN order_addresses ON orders.order_user_id = order_addresses.order_user_id "
0
- sql << "WHERE orders.order_number = ? "
0
- sql << "OR order_addresses.first_name LIKE ? "
0
- sql << "OR order_addresses.last_name LIKE ? "
0
- sql << "OR CONCAT(order_addresses.first_name, ' ', order_addresses.last_name) LIKE ? "
0
- sql << "ORDER BY orders.created_on DESC "
0
- sql << "LIMIT #{limit_sql}" if limit_sql
0
- arg_arr = [sql, search_term, "%#{search_term}%", "%#{search_term}%", "%#{search_term}%"]
0
- if (count == true) then
0
- # Finds orders by country
0
- def self.find_by_country(country_id, count=false, limit_sql=nil)
0
- if (count == true) then
0
- sql = "SELECT COUNT(*) "
0
- sql = "SELECT DISTINCT orders.* "
0
- sql << "INNER JOIN order_users ON order_users.id = orders.order_user_id "
0
- sql << "INNER JOIN order_addresses ON ( "
0
- sql << " order_addresses.country_id = ? AND order_addresses.order_user_id = order_users.id "
0
- arg_arr = [sql, country_id]
0
- if (count == true) then
0
- # Generates a unique order number.
0
- # This number isn't ID because we want to mask that from the customers.
0
- def self.generate_order_number
0
- random = rand(999999999)
0
- record = first(:conditions => ['order_number = ?', random])
0
- # Returns array of sales totals (hash) for a given year.
0
- def self.get_totals_for_year(year)
0
- sql = "SELECT COUNT(*) AS number_of_sales, SUM(product_cost) AS sales_total, "
0
- sql << "SUM(tax) AS tax, SUM(shipping_cost) AS shipping "
0
- sql << "WHERE YEAR(created_on) = ? "
0
- sql << "AND MONTH(created_on) = ? "
0
- sql << "AND (order_status_code_id = 5 OR order_status_code_id = 6 OR order_status_code_id = 7) "
0
- months[i] = self.find_by_sql([sql, year, i])[0]
0
- months[i] = self.find_by_sql([sql, year])[0]
0
- # Gets a CSV string that represents an order list.
0
- def self.get_csv_for_orders(order_list)
0
- csv_string = FasterCSV.generate do |csv|
0
- # Do header generation 1st
0
- "OrderNumber", "Company", "ShippingType", "Date",
0
- "BillLastName", "BillFirstName", "BillAddress", "BillCity",
0
- "BillState", "BillZip", "BillCountry", "BillTelephone",
0
- "ShipLastName", "ShipFirstName", "ShipAddress", "ShipCity",
0
- "ShipState", "ShipZip", "ShipCountry", "ShipTelephone",
0
- "Quantity1", "Item2", "Quantity2", "Item3", "Quantity3", "Item4",
0
- "Quantity4", "Item5", "Quantity5", "Item6", "Quantity6", "Item7",
0
- "Quantity7", "Item8", "Quantity8", "Item9", "Quantity9", "Item10",
0
- "Quantity10", "Item11", "Quantity11", "Item12", "Quantity12", "Item13",
0
- "Quantity13", "Item14", "Quantity14", "Item15", "Quantity15", "Item16",
0
- for order in order_list
0
- bill = order.billing_address
0
- ship = order.shipping_address
0
- pretty_date = order.created_on.strftime("%m/%d/%y")
0
- if !order.order_shipping_type.nil?
0
- ship_code = order.order_shipping_type.code
0
- order.order_number, '', ship_code, pretty_date,
0
- bill.last_name, bill.first_name, bill.address, bill.city,
0
- bill.state, bill.zip, bill.country.name, bill.telephone,
0
- ship.last_name, ship.first_name, ship.address, ship.city,
0
- ship.state, ship.zip, ship.country.name, ship.telephone
0
- # Generate spaces for items up to 16 deep
0
- item = order.order_line_items[i]
0
- if !item.nil? && !item.product.nil? then
0
- item_arr << item.product.code
0
- item_arr << item.quantity
0
- # Add csv string by joining arrays
0
- csv << order_arr.concat(item_arr)
0
- # Returns an XML string for each order in the order list.
0
- # This format is for sending orders to Tony's Fine Foods
0
- def self.get_xml_for_orders(order_list)
0
- xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
0
- for order in order_list
0
- if order.order_shipping_type
0
- shipping_type = order.order_shipping_type.code
0
- #pretty_date = order.created_on.strftime("%m/%d/%y")
0
- pretty_date = order.created_on
0
- xml << " <date>#{pretty_date}</date>\n"
0
- xml << " <shippingCode>#{shipping_type}</shippingCode>\n"
0
- xml << " <invoiceNumber>#{order.order_number}</invoiceNumber>\n"
0
- xml << " <emailAddress>#{order.order_user.email_address}</emailAddress>\n"
0
- address = order.shipping_address
0
- xml << " <shippingAddress>\n"
0
- xml << " <firstName>#{address.first_name}</firstName>\n"
0
- xml << " <lastName>#{address.last_name}</lastName>\n"
0
- xml << " <address1>#{address.address}</address1>\n"
0
- xml << " <address2></address2>\n"
0
- xml << " <city>#{address.city}</city>\n"
0
- xml << " <state>#{address.state}</state>\n"
0
- xml << " <zip>#{address.zip}</zip>\n"
0
- xml << " <countryCode>#{address.country.fedex_code}</countryCode>\n"
0
- xml << " <telephone>#{address.telephone}</telephone>\n"
0
- xml << " </shippingAddress>\n"
0
- for item in order.order_line_items
0
- xml << " <name>#{item.product.name}</name>\n"
0
- xml << " <id>#{item.product.code}</id>\n"
0
- xml << " <quantity>#{item.quantity}</quantity>\n"
0
- # INSTANCE METHODS ==========================================================
0
- # Shortcut to find order_line_item for a promotion that has been applied.
0
- def promotion_line_item
0
- return self.order_line_items.find_by_name(self.promotion.description)
0
- code = OrderStatusCode.first(:id => self.order_status_code_id)
0
- # Total for the order, including shipping and tax.
0
- logger.info "CALCULATING SHIPPING TOTAL"
0
- logger.info "LINE ITEMS TOTAL: #{self.line_items_total}"
0
- logger.info "SHIPPING COST: #{self.shipping_cost}"
0
- logger.info "TAX COST: #{self.tax_cost}"
0
- self.line_items_total + self.shipping_cost + self.tax_cost
0
- # The tax of items if applied.
0
- (self.line_items_total) * (self.tax/100)
0
- return "#{billing_address.first_name} #{billing_address.last_name}"
0
- # Sets line items from the product output table on the edit page.
0
- # Deletes any line items with a quantity of 0.
0
- # Adds line items with a quantity > 0.
0
- # This is called from update in our controllers.
0
- # What's passed looks something like this...
0
- # @products = {'1' => {'quantity' => 2}, '2' => {'quantity' => 0}, etc}
0
- def line_items=(products)
0
- # Clear out all line items
0
- self.order_line_items.clear
0
- # Go through all products
0
- products.each do |id, product|
0
- quantity = product['quantity']
0
- if quantity.blank? then
0
- quantity = Integer(quantity)
0
- if (quantity > 0) then
0
- new_item = self.order_line_items.build
0
- logger.info("\n\nBUILDING NEW LINE ITEM\n")
0
- logger.info(new_item.inspect+"\n")
0
- new_item.quantity = quantity
0
- new_item.unit_price = Item[:id].price
0
- # Do we have a valid transaction id
0
- def contains_valid_transaction_id?()
0
- return (!self.auth_transaction_id.blank? && self.auth_transaction_id != 0)
0
- # Determines if an order has a line item based on product id
0
- def has_line_item?(id)
0
- self.order_line_items.each do |item|
0
- return true if item.id == id
0
- # Gets quantity of a product if exists in current line items.
0
- def get_line_item_quantity(id)
0
- self.order_line_items.each do |item|
0
- return item.quantity if item.id == id
0
- # Gets a subtotal for line items based on product id
0
- def get_line_item_total(id)
0
- self.order_line_items.each do |item|
0
- return item.total if item.id == id
0
- # Grabs the total amount of all line items associated with this order
0
- for item in self.order_line_items
0
- # Adds a new order note from the edit page.
0
- # We display notes as read-only, so we only have to use a text field
0
- # instead of multiple records.
0
- time = Time.now.strftime("%m-%d-%y %I:%M %p")
0
- new_note = "<p>#{note}<br/>"
0
- new_note << "<span class=\"info\">"
0
- new_note << "[#{time}]"
0
- new_note << "</span></p>"
0
- if self.notes.blank? then
0
- self.notes << new_note
0
- # Calculates the weight of an order
0
- self.order_line_items.each do |item|
0
- weight += item.quantity * item.product.weight rescue 0
0
- # Gets a flat shipping price for an order.
0
- # This is if we're not using live rate calculation usually
0
- # A lot of people will want this overridden in their app
0
- def get_flat_shipping_price
0
- return Preference.find_by_name('store_handling_fee').value.to_f
0
- # Gets all LIVE shipping prices for an order.
0
- # Returns an array of OrderShippingTypes
0
- def get_shipping_prices
0
- # If they're in the USA
0
- address = self.shipping_address
0
- # TODO - set this country_id as a preference in the admin UI
0
- if address.country_id == 1 then
0
- shipping_types = OrderShippingType.get_domestic
0
- shipping_types = OrderShippingType.get_foreign
0
- for type in shipping_types
0
- type.calculate_price(self.weight)
0
- # Runs an order transaction.
0
- # Farms out the work to an Authorize.net or PayPal method
0
- # (or one of your devising).
0
- # Should return TRUE if the process is successful.
0
- # Should return AN ERROR MESSAGE if not...
0
- cc_processor = Order.get_cc_processor
0
- if cc_processor == Preference::CC_PROCESSORS[0]
0
- run_transaction_authorize
0
- elsif cc_processor == Preference::CC_PROCESSORS[1]
0
- run_transaction_paypal_ipn
0
- throw "The currently set preference for cc_processor is not recognized. You might want to add it to the code..."
0
- # Check to see which cc processor is used
0
- def self.get_cc_processor
0
- Preference.find_by_name('cc_processor').value
0
- # Get the login info for the cc processor (if any)
0
- Preference.find_by_name('cc_login').value
0
- # Runs an order through Authorize.net
0
- def run_transaction_authorize
0
- ba = self.billing_address
0
- # For debugging with a test account...
0
- # ActiveMerchant::Billing::Base.mode = :test