module JamRuby class Retailer < ActiveRecord::Base GUITAR_CENTER = 'guitar_center' include HtmlSanitize html_sanitize strict: [:name] attr_accessor :updating_avatar, :password, :should_validate_password attr_accessible :original_fpfile, :cropped_fpfile, :cropped_large_fpfile, :cropped_s3_path, :cropped_large_s3_path, :photo_url, :large_photo_url, :crop_selection belongs_to :posa_cards, class_name: 'JamRuby::PosaCard' belongs_to :user, class_name: ::JamRuby::User, inverse_of: :owned_retailer belongs_to :affiliate_partner, class_name: "JamRuby::AffiliatePartner" has_many :teachers, class_name: "JamRuby::Teacher" has_many :retailer_invitations, class_name: 'JamRuby::RetailerInvitation' has_many :teacher_payments, class_name: 'JamRuby::TeacherPayment' has_many :teacher_distributions, class_name: 'JamRuby::TeacherDistribution' has_many :sales, class_name: 'JamRuby::Sale' has_many :sale_line_items, class_name: 'JamRuby::SaleLineItem' has_many :lesson_bookings, class_name: 'JamRuby::LessonBooking' validates :user, presence: true #validates :slug, presence: true validates :enabled, inclusion: {in: [true, false]} validates_length_of :password, minimum: 6, maximum: 100, :if => :should_validate_password after_create :create_affiliate after_create :create_slug # before_save :stringify_avatar_info, :if => :updating_avatar def create_slug if self.slug.blank? self.slug = self.id.to_s end self.save! end def create_affiliate if affiliate_partner.nil? AffiliatePartner.create_from_retailer(self) end end def encrypt(password) BCrypt::Password.create(password, cost: 12).to_s end def matches_password(password) if password.blank? return false end begin # we init passwordfield as a UUID, which is a bogus hash; so if we see UUId, we know retailer has no password yet UUIDTools::UUID.parse(self.encrypted_password) return false rescue ArgumentError end BCrypt::Password.new(self.encrypted_password) == password end def update_payment(split) if split[:teacher] && split[:teacher].is_a?(Integer) && split[:retailer] && split[:retailer].is_a?(Integer) teacher_split = split[:teacher] retailer_split = split[:retailer] if (teacher_split >= 0 && teacher_split <= 100) && (retailer_split >= 0 && retailer_split <= 100) && (teacher_split + retailer_split == 100) self.payment = split.to_json end end end def update_from_params(params) self.name = params[:name] if params[:name].present? self.city = params[:city] self.state = params[:state] self.slug = params[:slug] if params[:slug].present? if params[:split] self.update_payment(params[:split]) end if params[:password].present? self.should_validate_password = true self.password = params[:password] self.encrypted_password = encrypt(params[:password]) end self.save end # should be of form {teacher: 0-100, retailer: 0-100} def payment_details if self.payment JSON.parse(self.payment) else {"teacher" =>100, "retailer" => 0} end end def owner user end def self.guitar_center Retailer.find_by_special(GUITAR_CENTER) end def is_guitar_center? return special == GUITAR_CENTER end def validate_avatar_info if updating_avatar # we want to mak sure that original_fpfile and cropped_fpfile seems like real fpfile info objects (i.e, json objects from filepicker.io) errors.add(:original_fpfile, ValidationMessages::INVALID_FPFILE) if self.original_fpfile.nil? || self.original_fpfile["key"].nil? || self.original_fpfile["url"].nil? errors.add(:cropped_fpfile, ValidationMessages::INVALID_FPFILE) if self.cropped_fpfile.nil? || self.cropped_fpfile["key"].nil? || self.cropped_fpfile["url"].nil? errors.add(:cropped_large_fpfile, ValidationMessages::INVALID_FPFILE) if self.cropped_large_fpfile.nil? || self.cropped_large_fpfile["key"].nil? || self.cropped_large_fpfile["url"].nil? end end def escape_filename(path) dir = File.dirname(path) file = File.basename(path) "#{dir}/#{ERB::Util.url_encode(file)}" end def update_avatar(original_fpfile, cropped_fpfile, cropped_large_fpfile, crop_selection, aws_bucket) self.updating_avatar = true cropped_s3_path = cropped_fpfile["key"] cropped_large_s3_path = cropped_large_fpfile["key"] self.update_attributes( :original_fpfile => original_fpfile.to_json, :cropped_fpfile => cropped_fpfile.to_json, :cropped_large_fpfile => cropped_large_fpfile.to_json, :cropped_s3_path => cropped_s3_path, :cropped_large_s3_path => cropped_large_s3_path, :crop_selection => crop_selection.to_json, :photo_url => S3Util.url(aws_bucket, escape_filename(cropped_s3_path), :secure => true), :large_photo_url => S3Util.url(aws_bucket, escape_filename(cropped_large_s3_path), :secure => true) ) end def delete_avatar(aws_bucket) User.transaction do unless self.cropped_s3_path.nil? S3Util.delete(aws_bucket, File.dirname(self.cropped_s3_path) + '/cropped.jpg') S3Util.delete(aws_bucket, self.cropped_s3_path) S3Util.delete(aws_bucket, self.cropped_large_s3_path) end return self.update_attributes( :original_fpfile => nil, :cropped_fpfile => nil, :cropped_large_fpfile => nil, :cropped_s3_path => nil, :cropped_large_s3_path => nil, :photo_url => nil, :crop_selection => nil, :large_photo_url => nil ) end end def stringify_avatar_info # fpfile comes in as a hash, which is a easy-to-use and validate form. However, we store it as a VARCHAR, # so we need t oconvert it to JSON before storing it (otherwise it gets serialized as a ruby object) # later, when serving this data out to the REST API, we currently just leave it as a string and make a JSON capable # client parse it, because it's very rare when it's needed at all self.original_fpfile = original_fpfile.to_json if !original_fpfile.nil? && original_fpfile.class != String self.cropped_fpfile = cropped_fpfile.to_json if !cropped_fpfile.nil? && cropped_fpfile.class != String self.crop_selection = crop_selection.to_json if !crop_selection.nil? && crop_selection.class != String end end end