merge develop

This commit is contained in:
Seth Call 2016-07-02 21:17:24 -05:00
commit 5fe49e4b15
1166 changed files with 133618 additions and 8198 deletions

File diff suppressed because one or more lines are too long

View File

@ -27,6 +27,7 @@ gem 'coffee-rails' #, '~> 3.2.1'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', :platforms => :ruby
gem 'kickbox'
gem 'uglifier' #, '>= 1.0.3'
# this version is pinned due to this: https://github.com/gregbell/active_admin/issues/1939
@ -71,9 +72,13 @@ gem 'iso-639'
gem 'rubyzip'
gem 'sanitize'
gem 'slim'
gem 'influxdb', '0.1.8'
gem 'influxdb-rails', '0.1.10'
#gem 'influxdb', '0.1.8'
#gem 'influxdb-rails', '0.1.10'
gem 'recurly'
gem 'sendgrid_toolkit', '>= 1.1.1'
gem 'stripe'
gem 'zip-codes'
gem 'email_validator'
group :libv8 do
gem 'libv8', "~> 4.5.95"
@ -100,7 +105,6 @@ end
group :development, :test do
gem 'capybara'
gem 'rspec-rails', '2.14.2'
gem 'guard-rspec'
gem 'jasmine', '1.3.1'
gem 'execjs', '1.4.0'
#gem 'therubyracer' #, '0.11.0beta8'

View File

@ -1,3 +1,4 @@
#!/usr/bin/env rake
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

View File

@ -0,0 +1,37 @@
ActiveAdmin.register JamRuby::AffiliateQuarterlyPayment, :as => 'Affiliate Quarterly Payments' do
menu :label => 'Quarterly Reports', :parent => 'Affiliates'
config.sort_order = 'due_amount_in_cents DESC'
config.batch_actions = false
config.clear_action_items!
config.filters = true
config.per_page = 50
config.paginate = true
filter :affiliate_partner
filter :year
filter :quarter
filter :closed
filter :paid
form :partial => 'form'
index do
# default_actions # use this for all view/edit/delete links
column 'Year' do |oo| oo.year end
column 'Quarter' do |oo| oo.quarter end
column 'Partner' do |oo| link_to(oo.affiliate_partner.display_name, oo.affiliate_partner.admin_url, {:title => oo.affiliate_partner.display_name}) end
column "Due (\u00A2)" do |oo| oo.due_amount_in_cents end
column 'JamTracks Sold' do |oo| oo.jamtracks_sold end
column 'Paid' do |oo| oo.paid end
column 'Closed' do |oo| oo.paid end
end
controller do
end
end

View File

@ -0,0 +1,36 @@
ActiveAdmin.register JamRuby::AffiliateTrafficTotal, :as => 'Affiliate Daily Stats' do
menu :label => 'Daily Stats', :parent => 'Affiliates'
config.sort_order = 'referral_user_count DESC'
config.batch_actions = false
config.clear_action_items!
config.filters = true
config.per_page = 50
config.paginate = true
filter :affiliate_partner
filter :day
filter :signups
filter :visits
form :partial => 'form'
scope("Active", default: true) { |scope| scope.where('visits != 0 or signups != 0').order('day desc') }
index do
# default_actions # use this for all view/edit/delete links
column 'Day' do |oo| oo.day end
column 'Partner' do |oo| link_to(oo.affiliate_partner.display_name, oo.affiliate_partner.admin_url, {:title => oo.affiliate_partner.display_name}) end
column 'Signups' do |oo| oo.signups end
column 'Visits' do |oo| oo.visits end
end
controller do
end
end

View File

@ -2,15 +2,18 @@ ActiveAdmin.register JamRuby::User, :as => 'Referrals' do
menu :label => 'Referrals', :parent => 'Affiliates'
config.sort_order = 'created_at DESC'
config.batch_actions = false
config.clear_action_items!
config.filters = false
config.filters = true
filter :affiliate_referral
index do
column 'User' do |oo| link_to(oo.name, "http://www.jamkazam.com/client#/profile/#{oo.id}", {:title => oo.name}) end
column 'User' do |oo| link_to(oo.name, oo.admin_url, {:title => oo.name}) end
column 'Email' do |oo| oo.email end
column 'Created' do |oo| oo.created_at end
column 'Partner' do |oo| oo.affiliate_referral.partner_name end
column 'Partner' do |oo| oo.affiliate_referral.display_name end
end
controller do

View File

@ -6,10 +6,12 @@ ActiveAdmin.register JamRuby::AffiliatePartner, :as => 'Affiliates' do
config.batch_actions = false
# config.clear_action_items!
config.filters = false
config.per_page = 50
config.paginate = true
form :partial => 'form'
scope("Active", default: true) { |scope| scope.where('partner_user_id IS NOT NULL') }
scope("Active", default: true) { |scope| scope.where('partner_user_id IS NOT NULL').order('referral_user_count desc') }
scope("Unpaid") { |partner| partner.unpaid }
index do

View File

@ -0,0 +1,87 @@
ActiveAdmin.register_page "CampaignSpend" do
menu :parent => 'JamClass'
page_action :create_spend, :method => :post do
campaign = params[:jam_ruby_campaign_spend][:campaign]
year = params[:jam_ruby_campaign_spend][:year]
month = params[:jam_ruby_campaign_spend][:month]
spend = params[:jam_ruby_campaign_spend][:spend]
if campaign.blank?
redirect_to admin_campaignspend_path, :notice => "No campaign defined! Nothing done."
return
elsif spend.blank?
redirect_to admin_campaignspend_path, :notice => "No spend defined! Nothing done."
return
elsif year.blank? || month.blank?
spend = spend.to_f
# get all cohorts for a given campaign
campaign_cohorts = JamClassReport.where(campaign: campaign).where("cohort IS NOT NULL")
year_months = []
campaign_cohorts.each do |cohort|
year_month = {year: cohort.cohort.year, month: cohort.cohort.month}
year_months << year_month
end
if campaign_cohorts.length > 0
per_month = spend / campaign_cohorts.length
year_months.each do |year_month|
campaign_spend = CampaignSpend.where(campaign: campaign).where(year: year_month[:year]).where(month: year_month[:month]).first
if campaign_spend.nil?
campaign_spend = CampaignSpend.new
end
campaign_spend.campaign = campaign
campaign_spend.month = year_month[:month]
campaign_spend.year = year_month[:year]
campaign_spend.spend = per_month
campaign_spend.save!
end
else
redirect_to admin_campaignspend_path, :notice => "No data found for campaign: #{campaign}"
return
end
redirect_to admin_campaignspend_path, :notice => "Campaign #{campaign} updated with a per month value of $#{per_month} (#{year_months.length} months worth of data found)"
else
campaign_spend = CampaignSpend.where(campaign: campaign).where(year: year).where(month: month).first
if campaign_spend.nil?
campaign_spend = CampaignSpend.new
end
campaign_spend.campaign = campaign
campaign_spend.month = month
campaign_spend.year = year
campaign_spend.spend = spend
campaign_spend.save!
redirect_to admin_campaignspend_path, :notice => "Campaign spend updated: #{campaign}:#{year}-#{month} = $#{spend}"
end
end
content do
para do
link_to "JamClass Report", admin_jamclassreports_path
end
para do
semantic_form_for CampaignSpend.new, :url => admin_campaignspend_create_spend_path, :builder => ActiveAdmin::FormBuilder do |f|
f.inputs "Campaign Spend" do
f.input :spend, :required => true, hint: "If you leave year or month blank, the system will divide up the specified spend amount here across all months seen for this campaign."
f.input :campaign, :as => :select, hint: "If this appears empty or incomplete, visit the JamClass Report page (link above) and come back.", :required => true, :collection => JamClassReport.select('campaign').group('campaign').map(&:campaign)
f.input :year, :as => :select, :hint => "Year of campaign spend (optional)", :collection => [Date.today.year, Date.today.year - 1]
f.input :month, :as => :select, :hint => "Month of campaign (optional)", :collection => (1..12).map { |m| [Date::MONTHNAMES[m], m] }
end
f.actions
end
end
end
end

View File

@ -0,0 +1,29 @@
ActiveAdmin.register JamRuby::ChatMessage, :as => 'ChatMessage' do
# Note: a lame thing is it's not obvious how to make it search on email instead of user_id.
filter :music_session_id
filter :user_id
menu :parent => 'Misc'
config.per_page = 200
config.sort_order = 'created_at DESC'
scope("Global", default:true) { |scope|
scope.where("channel = 'global'")
}
scope("Session", ) { |scope|
scope.where("channel = 'session'")
}
index do
column 'User' do |oo| link_to(oo.user.email, oo.user.admin_url, {:title => oo.user.email}) end
column "Timestamp" do |post|
(post.created_at).strftime('%b %d %Y, %H:%M')
end
column "Message" do |post|
post.message
end
actions
end
end

View File

@ -1,28 +1,27 @@
ActiveAdmin.register JamRuby::CrashDump, :as => 'Crash Dump' do
# Note: a lame thing is it's not obvious how to make it search on email instead of user_id.
filter :timestamp
filter :user_email, :as => :string
filter :client_id
filter :user_id
menu :parent => 'Misc'
config.sort_order = 'created_at DESC'
index do
column 'User' do |oo| oo.user ? link_to(oo.user.email, oo.user.admin_url, {:title => oo.user.email}) : '' end
column "Client Version", :client_version
column "Client Type", :client_type
column "Download" do |post|
link_to 'Link', post.sign_url
end
column "Timestamp" do |post|
(post.timestamp || post.created_at).strftime('%b %d %Y, %H:%M')
end
column "Client Type", :client_type
column "Dump URL" do |post|
link_to post.uri, post.uri
column "Description" do |post|
post.description
end
column "User ID", :user_id
# FIXME (?): This isn't performant (though it likely doesn't matter). Could probably do a join.
column "User Email" do |post|
unless post.user_id.nil?
post.user_email
end
end
column "Client ID", :client_id
actions
end
end

View File

@ -0,0 +1,35 @@
ActiveAdmin.register JamRuby::DownloadTracker, :as => 'DownloadTrackers' do
menu :label => 'Download Trackers', :parent => 'JamTracks'
config.batch_actions = false
config.filters = true
config.per_page = 50
filter :remote_ip
index do
column 'User' do |oo| oo.user ? link_to(oo.user.email, oo.user.admin_url, {:title => oo.user.email}) : '' end
column 'Created' do |oo| oo.created_at end
column 'JamTrack' do |oo| oo.jam_track end
column 'Paid' do |oo| oo.paid end
column 'Blacklisted?' do |oo| IpBlacklist.listed(oo.remote_ip) ? 'Yes' : 'No' end
column 'Remote IP' do |oo| oo.remote_ip end
column "" do |oo|
link_to 'Blacklist This IP', "download_trackers/#{oo.id}/blacklist_by_ip"
end
end
member_action :blacklist_by_ip, :method => :get do
tracker = DownloadTracker.find(params[:id])
if !IpBlacklist.listed(tracker.remote_ip)
ip = IpBlacklist.new
ip.remote_ip = tracker.remote_ip
ip.save!
end
redirect_to admin_download_trackers_path, :notice => "IP address #{tracker.remote_ip} blacklisted."
end
end

View File

@ -0,0 +1,14 @@
ActiveAdmin.register JamRuby::EmailBlacklist, :as => 'Email Blacklist' do
menu :label => 'Email Blacklist', :parent => 'Operations'
config.sort_order = 'created_at desc'
config.batch_actions = false
index do
column :email
column :source
column :notes
column :created_at
end
end

View File

@ -32,6 +32,7 @@ ActiveAdmin.register_page "Fake Purchaser" do
jam_track_right.user = user
jam_track_right.jam_track = jam_track
jam_track_right.is_test_purchase = true
jam_track_right.version = jam_track.version
jam_track_right.save!
count = count + 1
end

View File

@ -0,0 +1,41 @@
ActiveAdmin.register_page "Giftcarduploads" do
menu :label => 'Gift Cards Upload', :parent => 'JamTracks'
page_action :upload_giftcards, :method => :post do
GiftCard.transaction do
puts params
file = params[:jam_ruby_gift_card][:csv]
array_of_arrays = CSV.read(file.tempfile.path)
array_of_arrays.each do |row|
if row.length != 1
raise "UKNONWN CSV FORMAT! Must be 1 column"
end
code = row[0]
gift_card = GiftCard.new
gift_card.code = code
gift_card.card_type = params[:jam_ruby_gift_card][:card_type]
gift_card.origin = file .original_filename
gift_card.save!
end
redirect_to admin_giftcarduploads_path, :notice => "Created #{array_of_arrays.length} gift cards!"
end
end
content do
semantic_form_for GiftCard.new, :url => admin_giftcarduploads_upload_giftcards_path, :builder => ActiveAdmin::FormBuilder do |f|
f.inputs "Upload Gift Cards" do
f.input :csv, as: :file, required: true, :label => "A single column CSV that contains ONE type of gift card (5 JamTrack, 10 JamTrack, etc)"
f.input :card_type, required:true, as: :select, :collection => JamRuby::GiftCard::CARD_TYPES
end
f.actions
end
end
end

View File

@ -0,0 +1,24 @@
ActiveAdmin.register JamRuby::GiftCard, :as => 'GiftCards' do
menu :label => 'Gift Cards', :parent => 'JamTracks'
config.batch_actions = false
config.filters = true
config.per_page = 50
scope("Redeemed Most Recently", default: true) { |scope| scope.where('user_id IS NOT NULL').order('updated_at DESC') }
scope("Available") { |scope| scope.where('user_id is NULL') }
filter :card_type
filter :origin
filter :code
index do
column 'User' do |oo| oo.user ? link_to(oo.user.email, oo.user.admin_url, {:title => oo.user.email}) : '' end
column 'Code' do |oo| oo.code end
column 'Card Type' do |oo| oo.card_type end
column 'Origin' do |oo| oo.origin end
column 'Created' do |oo| oo.created_at end
end
end

View File

@ -0,0 +1,20 @@
ActiveAdmin.register JamRuby::User, :as => 'SchoolInterest' do
menu :label => 'Interested in Schools', :parent => 'JamClass'
config.sort_order = 'created_at desc'
config.batch_actions = false
config.per_page = 100
config.paginate = true
config.filters = false
scope("All", default: true) { |scope| scope.where(school_interest: true) }
index do
column "Name" do |user|
span do
link_to "#{user.name} (#{user.email})", "#{Rails.application.config.external_root_url}/client#/profile/#{user.id}"
end
end
end
end

View File

@ -0,0 +1,13 @@
ActiveAdmin.register JamRuby::IpBlacklist, :as => 'IP Blacklist' do
menu :label => 'IP Blacklist', :parent => 'Operations'
config.sort_order = 'created_at desc'
config.batch_actions = false
index do
column :remote_ip
column :notes
column :created_at
end
end

View File

@ -0,0 +1,13 @@
ActiveAdmin.register JamRuby::IpWhitelist, :as => 'IP Whitelist' do
menu :label => 'IP Whitelist', :parent => 'Operations'
config.sort_order = 'created_at desc'
config.batch_actions = false
index do
column :remote_ip
column :notes
column :created_at
end
end

View File

@ -0,0 +1,14 @@
ActiveAdmin.register_page "Jam Class Knobs" do
menu :parent => 'JamClass'
page_action :force_hourly, :method => :post do
Resque.enqueue(HourlyJob)
redirect_to admin_jam_class_knobs_path, :notice => "Re-running the Hourly Job. Lessons will be analysed; any payments will be attempted that should be, etc"
end
action_item do
link_to "Force Hourly Background Job", admin_jam_class_knobs_force_hourly_path, :method => :post
end
end

View File

@ -0,0 +1,66 @@
ActiveAdmin.register_page "JamClassReports", as: "JamClass Cohort Report" do
menu :parent => 'JamClass'
content :title => "JamClass Report" do
para do
link_to "Campaign Spend", admin_campaignspend_path
end
para do
table_for JamClassReport.analyse do
column "Campaign" do |r|
if r.campaign.nil?
"N/A"
else
r.campaign
end
end
column "Cohort" do |r|
if r.cohort.nil?
"Total"
else
"#{Date::ABBR_MONTHNAMES[r.cohort.month]} #{r.cohort.year}"
end
end
column "Spend" do |r|
if r.spend.nil?
"N/A"
else
r.spend
end
end
column "Registrations", :registrations
column "TD Customers", :td_customers
column "JamClass Revenues", :jamclass_rev
column "TD4", :td4
column "TD2", :td2
column "TD1", :td1
column "Spend/TD" do |r|
if r.spend_td.nil?
"N/A"
else
r.spend_td
end
end
column "% 0 BC" do |r|
(r.purchases0 * 100).round
end
column "% 1 BC" do |r|
(r.purchases1 * 100).round
end
column "% 2 BC" do |r|
(r.purchases2 * 100).round
end
column "% 3 BC" do |r|
(r.purchases3 * 100).round
end
column "% 4+ BC" do |r|
(r.purchases_rest * 100).round
end
end
end
end
end

View File

@ -5,13 +5,17 @@ ActiveAdmin.register JamRuby::JamTrack, :as => 'JamTracks' do
config.sort_order = 'name_asc'
config.batch_actions = false
filter :name
filter :original_artist
filter :genres
filter :status, :as => :select, collection: JamRuby::JamTrack::STATUS
scope("Default", default: true) { |scope| scope }
scope("Onboarding TODO") { |scope| scope.where('onboarding_exceptions is not null') }
scope("Tency Only") { |scope| scope.joins('INNER JOIN jam_track_licensors as licensors ON jam_tracks.licensor_id = licensors.id').where("licensors.name = 'Tency Music'") }
scope("Onboarding TODO w/ Tency Only") { |scope| scope.joins('INNER JOIN jam_track_licensors as licensors ON jam_tracks.licensor_id = licensors.id').where("licensors.name = 'Tency Music'").where('onboarding_exceptions is not null') }
scope("TimTracks Only") { |scope| scope.joins('INNER JOIN jam_track_licensors as licensors ON jam_tracks.licensor_id = licensors.id').where("licensors.name = 'Tim Waurick'") }
scope("Drumma Boy Only") { |scope| scope.joins('INNER JOIN jam_track_licensors as licensors ON jam_tracks.licensor_id = licensors.id').where("licensors.name = 'Drumma Boy'") }
# scope("Onboarding TODO w/ Tency Only") { |scope| scope.joins('INNER JOIN jam_track_licensors as licensors ON jam_tracks.licensor_id = licensors.id').where("licensors.name = 'Tency Music'").where('onboarding_exceptions is not null') }
form :partial => 'form'

View File

@ -0,0 +1,15 @@
ActiveAdmin.register JamRuby::Jamblaster, :as => 'Jamblaster' do
menu :label => 'JamBlasters', :parent => 'JamBlaster'
form do |f|
f.inputs 'New JamBlaster' do
f.input :user, required: true, collection: User.all, include_blank: false
f.input :serial_no, required: true
f.input :client_id, required: false
f.input :users, required: true, collection: User.all, include_blank: false
end
f.actions
end
end

View File

@ -0,0 +1,47 @@
ActiveAdmin.register JamRuby::LessonBooking, :as => 'LessonBookings' do
menu :label => 'Lesson Booking', :parent => 'JamClass'
config.sort_order = 'created_at desc'
config.batch_actions = false
config.per_page = 100
config.paginate = true
config.filters = false
scope("All", default: true ) { |scope| scope.unscoped.order('created_at desc') }
scope("Requested") { |scope| scope.unscoped.where(status: LessonBooking::STATUS_REQUESTED).order('created_at desc') }
scope("Approved") { |scope| scope.unscoped.approved.order('created_at desc') }
scope("Suspended" ) { |scope| scope.unscoped.suspended.order('created_at desc') }
scope("Canceled" ) { |scope| scope.unscoped.canceled.order('created_at desc') }
index do
column "User Link" do |lesson_booking|
span do
link_to "Web URL", "#{Rails.application.config.external_root_url}/client#/jamclass/lesson-booking/#{lesson_booking.id}"
end
end
column "Type" do |lesson_booking|
lesson_booking.display_type
end
column "Status" do |lesson_booking|
lesson_booking.status
end
column "Teacher" do |lesson_booking|
teacher = lesson_booking.teacher
span do
link_to "#{teacher.name} (#{teacher.email})", "#{Rails.application.config.external_root_url}/client#/profile/teacher/#{teacher.id}"
end
end
column "Student" do |lesson_booking|
student = lesson_booking.student
span do
link_to "#{student.name} (#{student.email})", "#{Rails.application.config.external_root_url}/client#/profile/#{student.id}"
end
end
end
show do
end
end

View File

@ -0,0 +1,129 @@
ActiveAdmin.register JamRuby::LessonSession, :as => 'LessonSessions' do
menu :label => 'Lesson Session', :parent => 'JamClass'
config.sort_order = 'created_at desc'
config.batch_actions = false
config.per_page = 100
config.paginate = true
config.filters = false
scope("All", default: true) { |scope| scope.unscoped.order('created_at desc') }
scope("Requested") { |scope| scope.unscoped.where(status: LessonBooking::STATUS_REQUESTED).order('created_at desc') }
scope("Approved") { |scope| scope.unscoped.approved.order('created_at desc') }
scope("Suspended") { |scope| scope.unscoped.suspended.order('created_at desc') }
scope("Canceled") { |scope| scope.unscoped.canceled.order('created_at desc') }
scope("Missed") { |scope| scope.unscoped.missed.order('created_at desc') }
scope("Completed") { |scope| scope.unscoped.completed.order('created_at desc') }
index do
column "User Link" do |lesson_session|
lesson_booking = lesson_session.lesson_booking
span do
link_to "Web URL", "#{Rails.application.config.external_root_url}/client#/jamclass/lesson-booking/#{lesson_booking.id}"
end
end
column "Status" do |lesson_session|
link_to lesson_session.status, admin_lesson_session_path(lesson_session.id)
end
column "Start Time" do |lesson_session|
span do
if lesson_session.music_session.nil?
raise "Lessonsesison with no id #{lesson_session.id}"
else
lesson_session.music_session.pretty_scheduled_start(true)
end
end
br
span do
lesson_session.music_session.scheduled_start
end
end
column "Duration" do |lesson_session|
lesson_session.duration
end
column "Teacher" do |lesson_session|
teacher = lesson_session.teacher
span do
link_to "#{teacher.name} (#{teacher.email})", "#{Rails.application.config.external_root_url}/client#/profile/teacher/#{teacher.id}"
end
end
column "Student" do |lesson_session|
student = lesson_session.student
span do
link_to "#{student.name} (#{student.email})", "#{Rails.application.config.external_root_url}/client#/profile/#{student.id}"
end
end
end
show do
attributes_table do
row "User Link" do |lesson_session|
lesson_booking = lesson_session.lesson_booking
span do
link_to "Web URL", "#{Rails.application.config.external_root_url}/client#/jamclass/lesson-booking/#{lesson_booking.id}"
end
end
row "Status" do |lesson_session|
lesson_session.status
end
row "Start Time" do |lesson_session|
span do
lesson_session.music_session.pretty_scheduled_start(true)
end
br
span do
lesson_session.music_session.scheduled_start
end
end
row "Duration" do |lesson_session|
lesson_session.duration
end
row "Teacher" do |lesson_session|
teacher = lesson_session.teacher
span do
link_to "#{teacher.name} (#{teacher.email})", "#{Rails.application.config.external_root_url}/client#/profile/teacher/#{teacher.id}"
end
end
row "Student" do |lesson_session|
student = lesson_session.student
span do
link_to "#{student.name} (#{student.email})", "#{Rails.application.config.external_root_url}/client#/profile/#{student.id}"
end
end
row "Followup Emails Sent" do |lesson_session|
span do
lesson_session.sent_notices
end
end
row "Success" do |lesson_session|
span do
lesson_session.success
end
end
row "Billed" do |lesson_session|
span do
lesson_session.billed
end
end
row "Description" do |lesson_session|
span do
lesson_session.timed_description
end
end
row "Analysis" do |lesson_session|
if lesson_session.analysed
span style: "white-space: pre;" do
begin
JSON.pretty_generate(lesson_session.analysis_json)
rescue
"barf"
end
end
end
end
end
end
end

View File

@ -0,0 +1,38 @@
ActiveAdmin.register_page "Monthly Stats" do
menu :parent => 'Reports'
content :title => "Monthly Stats" do
h2 "Distinct Users Playing in Sessions"
table_for MusicSession.select([:month, :count]).find_by_sql("select date_trunc('month', msuh.created_at)::date as month, count(distinct(user_id)) from music_sessions_user_history msuh group by month order by month desc;") do
column "Month", Proc.new { |row| Date.parse(row.month).strftime('%B %Y') }
column "Users", :count
end
h2 "Music Sessions"
table_for MusicSession.select([:month, :count]).find_by_sql("select date_trunc('month', ms.created_at)::date as month, count(id) from music_sessions ms where started_at is not null group by month order by month desc;") do
column "Month", Proc.new { |row| Date.parse(row.month).strftime('%B %Y') }
column "Sessions", :count
end
h2 "Distinct Users Who Played with a JamTrack"
table_for MusicSession.select([:month, :count]).find_by_sql("select date_trunc('month', jts.created_at)::date as month, count(distinct(user_id)) from jam_track_sessions jts group by month order by month desc;") do
column "Month", Proc.new { |row| Date.parse(row.month).strftime('%B %Y') }
column "Users", :count
end
h2 "Music Sessions with JamTracks Played"
table_for MusicSession.select([:month, :count]).find_by_sql("select date_trunc('month', jts.created_at)::date as month, count(distinct(music_session_id)) from jam_track_sessions jts where session_type = 'session' group by month order by month desc;") do
column "Month", Proc.new { |row| Date.parse(row.month).strftime('%B %Y') }
column "Sessions", :count
end
h2 "JamTrack Web Player Sessions"
table_for MusicSession.select([:month, :count]).find_by_sql("select date_trunc('month', jts.created_at)::date as month, count(id) from jam_track_sessions jts where session_type = 'browser' group by month order by month desc;") do
column "Month", Proc.new { |row| Date.parse(row.month).strftime('%B %Y') }
column "Sessions", :count
end
end
end

6
admin/app/admin/news.rb Normal file
View File

@ -0,0 +1,6 @@
ActiveAdmin.register JamRuby::News, :as => 'News' do
menu :parent => 'Misc'
end

View File

@ -0,0 +1,43 @@
ActiveAdmin.register JamRuby::SaleLineItem, :as => 'Sale Line Items' do
menu :label => 'Line Items', :parent => 'Purchases'
config.sort_order = 'created_at DESC'
config.batch_actions = false
config.clear_action_items!
config.filters = true
config.per_page = 50
config.paginate = true
filter :affiliate_referral_id
filter :free
form :partial => 'form'
scope("Non Free", default: true) { |scope| scope.where(free: false).order('created_at desc') }
scope("Free") { |scope| scope.where(free: true).order('created_at desc') }
index do
# default_actions # use this for all view/edit/delete links
column 'Product' do |oo| oo.product end
column "Partner" do |oo|
link_to("#{oo.affiliate_referral.display_name} #{oo.affiliate_referral_fee_in_cents ? "#{oo.affiliate_referral_fee_in_cents}\u00A2" : ''}", oo.affiliate_referral.admin_url, {:title => oo.affiliate_referral.display_name}) if oo.affiliate_referral
end
column 'User' do |oo|
link_to(oo.sale.user.name, admin_user_path(oo.sale.user.id), {:title => oo.sale.user.name})
end
column 'Source' do |oo|
oo.sale.source
end
column 'When' do |oo|
oo.created_at
end
end
controller do
end
end

View File

@ -0,0 +1,50 @@
ActiveAdmin.register JamRuby::LessonSession, :as => 'SlowResponses' do
menu :label => 'Slow Responses', :parent => 'JamClass'
config.sort_order = 'created_at desc'
config.batch_actions = false
config.per_page = 100
config.paginate = true
config.filters = false
scope("Slow Responses", default: true) { |scope| scope.unscoped.slow_responses }
scope("Least Time Left") { |scope| scope.unscoped.least_time_left }
index do
column "Teacher" do |lesson_session|
teacher = lesson_session.teacher
span do
link_to "#{teacher.name} (#{teacher.email})", "#{Rails.application.config.external_root_url}/client#/profile/teacher/#{teacher.id}"
end
end
column "Student" do |lesson_session|
student = lesson_session.student
span do
link_to "#{student.name} (#{student.email})", "#{Rails.application.config.external_root_url}/client#/profile/#{student.id}"
end
end
column "Type" do |lesson_session|
link_to lesson_session.display_type
end
column "Start Time" do |lesson_session|
span do
if lesson_session.music_session.nil?
raise "Lessonsesison with no id #{lesson_session.id}"
else
lesson_session.music_session.pretty_scheduled_start(true)
end
end
end
column "Last student comms date" do |lesson_session|
lesson_session.last_student_comm_date
end
column "Days with no response" do |lesson_session|
"#{lesson_session.days_no_response} days"
end
end
end

View File

@ -0,0 +1,60 @@
ActiveAdmin.register JamRuby::User, :as => 'Students' do
menu :label => 'Students', :parent => 'JamClass'
config.sort_order = 'created_at desc'
config.batch_actions = false
config.per_page = 100
config.paginate = true
config.filters = false
def booked_anything(scope)
scope.joins(:student_lesson_bookings).where('lesson_bookings.active = true').uniq
end
scope("Default", default: true) { |scope| scope.where('is_a_student = true OR ((select count(id) from lesson_bookings where lesson_bookings.user_id = users.id) > 0)').order('users.ready_for_session_at IS NULL DESC') }
index do
column "Name" do |user|
link_to user.name, "#{Rails.application.config.external_root_url}/client#/profile/#{user.id}"
end
column "Email" do |user|
user.email
end
column "Location" do |user|
user.location(country = true)
end
column "Session Ready" do |user|
div do
if user.ready_for_session_at
span do
'YES'
end
else
span do
'NO'
end
span do
br
end
span do
link_to("mark as checked", mark_session_ready_admin_student_path(user.id), {confirm: "Mark as ready for session?"})
end
end
end
end
column "School" do |user|
if user.school
user.school.name
end
end
end
member_action :mark_session_ready, :method => :get do
resource.mark_session_ready
redirect_to :back
end
end

288
admin/app/admin/teachers.rb Normal file
View File

@ -0,0 +1,288 @@
ActiveAdmin.register JamRuby::Teacher, :as => 'Teachers' do
menu :label => 'Teachers', :parent => 'JamClass'
config.sort_order = 'created_at desc'
config.batch_actions = false
config.per_page = 100
config.paginate = true
config.filters = false
scope("All", default: true) { |scope| scope.unscoped.order("background_check_at > '#{(Date.today - 365).to_s}}' NULLS FIRST, ready_for_session_at IS NULL DESC") }
scope("All Sorted By Sign Up") { |scope| scope.unscoped.order("teachers.created_at DESC, background_check_at > '#{(Date.today - 365).to_s}}' NULLS FIRST, ready_for_session_at IS NULL DESC") }
scope("50% and Session Ready" ) { |scope| scope.unscoped.where('profile_pct >= ?', 50.0).where('ready_for_session_at IS NOT NULL').order("background_check_at > '#{(Date.today - 365).to_s}}' NULLS FIRST, ready_for_session_at IS NULL DESC") }
scope("50% and Not Session Ready" ) { |scope| scope.unscoped.where('profile_pct > ?', 50.0).where('ready_for_session_at IS NULL').order("background_check_at > '#{(Date.today - 365).to_s}}' NULLS FIRST, ready_for_session_at IS NULL DESC") }
index do
column "Name" do |teacher|
span do
link_to "#{teacher.user.name} (#{teacher.user.email})", "#{Rails.application.config.external_root_url}/client#/profile/teacher/#{teacher.user.id}"
end
end
column "Instruments & Genres" do |teacher|
div do
div do
teacher.instruments.join(', ')
end
br
div do
teacher.genres.join(', ')
end
end
end
column "Location" do |teacher|
teacher.user.location(country = true)
end
column "Profile %" do |teacher|
div do
span do
"#{teacher.pct_complete[:pct]}%"
end
br
span do
link_to "Detail", admin_teacher_path(teacher.id)
end
end
end
=begin
column "Background Check" do |teacher|
div do
if teacher.background_check_at
span do
teacher.background_check_at.to_date
end
span do
br
end
span do
link_to(mark_background_check_admin_teacher_path(teacher.id), {confirm: "Mark as background checked?"}) do
"mark as checked"
end
end
else
span do
''
end
span do
br
end
span do
link_to("mark as checked", mark_background_check_admin_teacher_path(teacher.id), {confirm: "Mark as background checked?"})
end
end
end
end
=end
column "Session Ready" do |teacher|
div do
if teacher.ready_for_session_at
span do
'YES'
end
else
span do
'NO'
end
span do
br
end
span do
link_to("mark as checked", mark_session_ready_admin_teacher_path(teacher.id), {confirm: "Mark as ready for session?"})
end
end
end
end
column "Top Teacher" do |teacher|
div do
if teacher.top_rated
span do
'YES'
end
span do
br
end
span do
link_to("mark not top", mark_not_top_admin_teacher_path(teacher.id), {confirm: "Mark as not top rated?"})
end
else
span do
'NO'
end
span do
br
end
span do
link_to("mark as top", mark_top_admin_teacher_path(teacher.id), {confirm: "Mark as top rated?"})
end
end
end
end
column "Signed Up" do |teacher|
teacher.created_at.to_date
end
column "School" do |teacher|
if teacher.school
teacher.school.name
end
end
end
show do
attributes_table do
row "Name" do |teacher|
link_to teacher.user.name, "#{Rails.application.config.external_root_url}/client#/profile/teacher/#{teacher.user.id}"
end
row "Email" do |teacher|
teacher.user.email
end
row "Location" do |teacher|
teacher.user.location(country = true)
end
row "Profile %" do |teacher|
div do
span do
"#{teacher.pct_complete[:pct]}%"
end
br
br
div do
h5 do "Completed Sections" end
teacher.pct_complete.each do |k, v|
if k != :pct && v
div do
k
end
end
end
br
br
h5 do "Uncompleted Sections" end
teacher.pct_complete.each do |k, v|
if k != :pct && !v
div do
k
end
end
end
end
end
end
=begin
row "Background Check" do |teacher|
div do
if teacher.background_check_at
span do
teacher.background_check_at.to_date
end
span do
br
end
span do
link_to(mark_background_check_admin_teacher_path(teacher.id), {confirm: "Mark as background checked?"}) do
"mark as checked"
end
end
else
span do
'NOT DONE'
end
span do
br
end
span do
link_to("mark as checked", mark_background_check_admin_teacher_path(teacher.id), {confirm: "Mark as background checked?"})
end
end
end
end
=end
row "Session Ready" do |teacher|
div do
if teacher.ready_for_session_at
span do
'YES'
end
else
span do
'NO'
end
span do
br
end
span do
link_to("mark as checked", mark_session_ready_admin_teacher_path(teacher.id), {confirm: "Mark as ready for session?"})
end
end
end
end
row "Top Teacher" do |teacher|
div do
if teacher.top_rated
span do
'YES'
end
span do
br
end
span do
link_to("mark not top", mark_not_top_admin_teacher_path(teacher.id), {confirm: "Mark as not top rated?"})
end
else
span do
'NO'
end
span do
br
end
span do
link_to("mark as top", mark_top_admin_teacher_path(teacher.id), {confirm: "Mark as top rated?"})
end
end
end
end
row "Signed Up" do |teacher|
teacher.created_at.to_date
end
row "School" do |teacher|
if teacher.school
teacher.school.name
end
end
end
end
member_action :mark_background_check, :method => :get do
resource.mark_background_checked
redirect_to :back
end
member_action :mark_session_ready, :method => :get do
resource.mark_session_ready
redirect_to :back
end
member_action :mark_top, :method => :get do
resource.mark_top_rated
redirect_to :back
end
member_action :mark_not_top, :method => :get do
resource.mark_not_top_rated
redirect_to :back
end
end

View File

@ -0,0 +1,102 @@
ActiveAdmin.register JamRuby::TestDrivePackage, :as => 'TestDrivePackage' do
menu :label => 'Test Drive Packages', :parent => 'JamClass'
config.sort_order = 'created_at desc'
config.batch_actions = false
config.per_page = 100
config.paginate = true
config.filters = false
form :partial => 'form'
controller do
=begin
def new
test_drive_package = TestDrivePackage.new
t = TestDrivePackageTeacher.new
t.test_drive_package = test_drive_package
test_drive_package.test_drive_package_teachers << t
t = TestDrivePackageTeacher.new
t.test_drive_package = test_drive_package
test_drive_package.test_drive_package_teachers << t
@test_drive_package = test_drive_package
puts "OK #{test_drive_package.test_drive_package_teachers.length}"
super
end
=end
# def create
# puts params.inspect
# hash = params[:jam_ruby_test_drive_package]
# package = TestDrivePackage.new
# package.name = hash[:name]
# package.package_type = hash[:package_type]
# package.description = hash[:description]
# if package.save
# redirect_to admin_test_drive_package_path(package.id)
# else
# redirect_to admin_test_drive_packages_path, :notice => "Unable to create package. Error: #{package.errors.first[1][0]}"
# end
#end
end
index do
column "Package ID" do |package|
link_to package.name, "#{APP_CONFIG.external_root_url}/landing/jamclass/students?utm-teachers=#{package.name}"
end
column "Package Type" do |package|
package.package_type
end
column "Teachers" do |package|
package.test_drive_package_teachers.each do |package_teacher|
span do
teacher = package_teacher.user
link_to "#{teacher.name} (#{teacher.email})", "#{Rails.application.config.external_root_url}/client#/profile/teacher/#{teacher.id}"
end
br
end
end
column "Detail" do |package|
link_to "Detail", admin_test_drive_package_path(package.id)
end
end
show do
attributes_table do
row "Package ID" do |package|
link_to package.name, "#{APP_CONFIG.external_root_url}/landing/jamclass/students?utm-teachers=#{package.name}"
end
row "Package Type" do |package|
package.package_type
end
row "Teachers" do |package|
package.test_drive_package_teachers.each do |package_teacher|
span do
teacher = package_teacher.user
link_to "#{teacher.name} (#{teacher.email})", "#{Rails.application.config.external_root_url}/client#/profile/teacher/#{teacher.id}"
end
br
end
end
row "Description" do |package|
package.description
end
end
end
end

View File

@ -0,0 +1,20 @@
ActiveAdmin.register_page "Top Selling JamTracks" do
menu :parent => 'Reports'
top_selling_jamtracks = JamTrack.select([:id, :original_artist, :name, :has_tap_in]).find_by_sql("select count(jam_tracks.id) as count , jam_tracks.id, original_artist, name, (jmep_text is not null) has_tap_in from jam_tracks inner join jam_track_rights on (jam_track_rights.jam_track_id = jam_tracks.id AND jam_track_rights.is_test_purchase = false) group by jam_tracks.id order by count(jam_tracks.id) desc ")
content :title => "Top Selling JamTracks" do
table_for top_selling_jamtracks do
column "Count", :count
column "Original Artist", :original_artist
column "Name", :name
column "Has Count-in", :has_tap_in
column "ID", :id
end
end
end

View File

@ -0,0 +1,13 @@
ActiveAdmin.register JamRuby::UserBlacklist, :as => 'User Blacklist' do
menu :label => 'User Blacklist', :parent => 'Operations'
config.sort_order = 'created_at desc'
config.batch_actions = false
index do
column :user
column :notes
column :created_at
end
end

View File

@ -9,7 +9,7 @@ ActiveAdmin.register JamRuby::User, :as => 'User Progression' do
config.filters = false
index do
column :email do |user| link_to(truncate(user.email, {:length => 12}), resource_path(user), {:title => "#{user.first_name} #{user.last_name} (#{user.email})"}) end
column :email do |user| link_to(truncate(user.email, {:length => 12}), resource_path(user), {:title => "#{user.name} (#{user.email})"}) end
column :updated_at do |uu| uu.updated_at.strftime(PROGRESSION_DATE) end
column :created_at do |uu| uu.created_at.strftime(PROGRESSION_DATE) end
column :city

View File

@ -0,0 +1,32 @@
ActiveAdmin.register JamRuby::User, :as => 'UserSource' do
menu :label => 'User Campaigns', :parent => 'Users'
config.sort_order = 'created_at DESC'
config.batch_actions = false
config.clear_action_items!
config.filters = false
scope("Most Recent First", default: true) { |scope| scope.unscoped.order('created_at desc')}
index do
column "Email" do |user|
user.email
end
column "Bought TestDrive" do |user|
!user.most_recent_test_drive_purchase.nil? ? "Yes" : "No"
end
column "UTM Source" do |user|
user.origin_utm_source
end
column "UTM Medium" do |user|
user.origin_utm_medium
end
column "UTM Campaign" do |user|
user.origin_utm_campaign
end
column "Referrer" do |user|
user.origin_referrer
end
end
end

View File

@ -0,0 +1,13 @@
ActiveAdmin.register JamRuby::UserWhitelist, :as => 'User Whitelist' do
menu :label => 'User Whitelist', :parent => 'Operations'
config.sort_order = 'created_at desc'
config.batch_actions = false
index do
column :user
column :notes
column :created_at
end
end

View File

@ -1,9 +1,13 @@
class ApplicationController < ActionController::Base
include ApplicationHelper
protect_from_forgery
before_filter :prepare_gon
def prepare_gon
@olark_enabled = false
gon.olark_box_start_hidden = false
gon.prefix = ENV['RAILS_RELATIVE_URL_ROOT'] || '/'
end
end

View File

@ -15,5 +15,25 @@ class EmailController < ApplicationController
headers['Content-Type'] ||= 'text/csv'
@users = User.where(subscribe_email: true)
# if specified, return only users that have redeemed or bought a JamTrack
if params[:any_jam_track]
@users = @users.select('DISTINCT users.id, email, first_name, last_name').joins(:sales => :sale_line_items).where("sale_line_items.product_type = 'JamTrack'")
end
end
def dump_teachers
if params[:code] != Rails.application.config.email_dump_code
render :text => "", :status => 404
return
end
headers['Content-Disposition'] = "attachment; filename=\"teacher-list.csv\""
headers['Content-Type'] ||= 'text/csv'
@users = User.joins(:teacher)
render "dump_emailables.csv.erb"
end
end

View File

@ -12,4 +12,19 @@ class JamTrackController < ApplicationController
render "jam_track/dump_released", :layout => nil
end
def dump_top_selling
if params[:code] != Rails.application.config.data_dump_code
render :text => "", :status => 404
return
end
@jam_tracks = JamTrack.select([:id, :original_artist, :name]).find_by_sql("select count(jam_tracks.id) as count , jam_tracks.id, original_artist, name, (jmep_text is not null) has_tap_in from jam_tracks inner join jam_track_rights on (jam_track_rights.jam_track_id = jam_tracks.id AND jam_track_rights.is_test_purchase = false) group by jam_tracks.id order by count(jam_tracks.id) desc ")
headers['Content-Disposition'] = "attachment; filename=\"top-selling-jam-tracks.csv\""
headers['Content-Type'] ||= 'text/csv'
render "jam_track/dump_top_selling", :layout => nil
end
end

View File

@ -1,4 +1,5 @@
module ApplicationHelper
end

View File

@ -2,6 +2,8 @@
<%= f.semantic_errors *f.object.errors.keys %>
<%= f.inputs do %>
<%= f.input(:partner_name, :input_html => {:maxlength => 128}) %>
<%= f.input(:entity_type, :as => :select, :collection => AffiliatePartner::ENTITY_TYPES) %>
<%= f.input(:rate) %>
<% end %>
<%= f.actions %>
<% end %>

View File

@ -13,6 +13,7 @@
= f.input :publisher, :input_html => { :rows=>1, :maxlength=>1000 }
= f.input :licensor, collection: JamRuby::JamTrackLicensor.all, include_blank: true
= f.input :genres
= f.input :year
= f.input :duration, hint: 'this should rarely need editing because it comes from the import process'
= f.input :sales_region, collection: JamRuby::JamTrack::SALES_REGION, include_blank: false
= f.input :price, :required => true, :input_html => {type: 'numeric'}

View File

@ -0,0 +1,20 @@
<%= semantic_form_for([:admin, @test_drive_package], html: {:multipart => true}, url: @test_drive_package.new_record? ? admin_test_drive_packages_path : "#{ENV['RAILS_RELATIVE_URL_ROOT']}/admin/test_drive_packages/#{@test_drive_package.id}") do |f| %>
<%= f.semantic_errors *f.object.errors.keys %>
<%= f.inputs do %>
<%= f.input :name, required: true, label: "Package ID", hint: "The name to use as the utm-teachers parameter in the student landing URL" %>
<%= f.input :package_type, required: true, label: "Package Type", as: :select, collection: ['1', '2', '4'], hint: "TestDrive package type" %>
<%= f.input :description, label: "Package Description", hint: "Admin-only friendly description of the package" %>
<%= f.semantic_fields_for :test_drive_package_teachers do |teacher| %>
<%= render 'test_drive_package_teacher_fields', f: teacher %>
<% end %>
<% if !@test_drive_package.new_record? %>
<div class="links">
<%= link_to_add_association 'Add Teacher', f, :test_drive_package_teachers, class: 'button', style: 'margin:20px;padding:10px 20px' %>
</div>
<% end %>
<%= f.actions %>
<% end %>
<% end %>

View File

@ -0,0 +1,8 @@
= f.inputs name: 'Teachers' do
ol.nested-fields
//= f.input :test_drive_package, :required=>true, value: @test_drive_package, include_blank: true
= f.input :user, :required=>true, collection: User.where(is_a_teacher: true, phantom: false), include_blank: true
= f.input :short_bio_temp
= link_to_remove_association "Delete Teacher", f, class: 'button', style: 'margin-left:10px'

View File

@ -1,2 +1,2 @@
<%- headers = ['email', 'name', 'unsubscribe_token'] -%>
<%= CSV.generate_line headers %><%- @users.each do |user| -%><%= CSV.generate_line([user.email, user.first_name, user.unsubscribe_token]) %><%- end -%>
<%= CSV.generate_line headers %><%- @users.each do |user| -%><%= CSV.generate_line([user.email, user.anonymous? ? '-' : user.first_name, user.unsubscribe_token]) %><%- end -%>

View File

@ -0,0 +1,2 @@
<%- headers = ['Artist Name', 'Song Name', 'ID', 'Count', 'Has Count-in'] -%>
<%= CSV.generate_line headers %><%- @jam_tracks.each do |jam_track| -%><%= CSV.generate_line([jam_track.original_artist, jam_track.name, jam_track.id, jam_track['count'], jam_track['has_tap_in']]) %><%- end -%>

View File

@ -111,6 +111,7 @@ module JamAdmin
config.redis_host = "localhost:6379"
config.email_social_alias = 'social@jamkazam.com'
config.email_alerts_alias = 'alerts@jamkazam.com' # should be used for 'oh no' server down/service down sorts of emails
config.email_generic_from = 'nobody@jamkazam.com'
config.email_smtp_address = 'smtp.sendgrid.net'
@ -154,5 +155,13 @@ module JamAdmin
config.jmep_dir = ENV['JMEP_DIR'] || File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "jmep"))
config.email_dump_code = 'rcAUyC3TZCbgGx4YQpznBRbNnQMXW5iKTzf9NSBfzMLsnw9dRQ'
config.data_dump_code = 'rcAUyC3TZCbgGx4Y3321eudbNnQMXW5iKTzf9NSBfzMLsnw9dRQ'
config.admin_port = ENV['ADMIN_PORT'] || 3333
config.admin_root_url = "#{config.external_protocol}#{config.external_hostname}#{(config.admin_port == 80 || config.admin_port == 443) ? '' : ':' + config.admin_port.to_s}"
config.download_tracker_day_range = 30
config.max_user_ip_address = 10
config.max_multiple_users_same_ip = 2
end
end

View File

@ -43,4 +43,5 @@ JamAdmin::Application.configure do
config.email_generic_from = 'nobody-dev@jamkazam.com'
config.email_alerts_alias = 'alerts-dev@jamkazam.com'
config.email_social_alias = 'social-dev@jamkazam.com'
end

View File

@ -0,0 +1,9 @@
class JamRuby::GiftCard
attr_accessor :csv
def process_csv
end
end

View File

@ -0,0 +1,5 @@
class JamRuby::Teacher
attr_accessible :short_bio, as: :admin
end

View File

@ -1,6 +1,8 @@
class JamRuby::User
attr_accessible :admin, :raw_password, :musician, :can_invite, :photo_url, :session_settings, :confirm_url, :email_template # :invite_email
attr_accessible :admin, :raw_password, :musician, :can_invite, :photo_url, :session_settings, :confirm_url, :teacher_attributes, :email_template # :invite_email
accepts_nested_attributes_for :teacher, allow_destroy: true
def raw_password
''

View File

@ -2,28 +2,5 @@ class JamRuby::JamTrack
# add a custom validation
attr_accessor :preview_generate_error
before_save :jmep_json_generate
validate :jmep_text_validate
def jmep_text_validate
begin
JmepManager.execute(self.jmep_text)
rescue ArgumentError => err
errors.add(:jmep_text, err.to_s)
end
end
def jmep_json_generate
self.licensor_id = nil if self.licensor_id == ''
self.jmep_json = nil if self.jmep_json == ''
self.time_signature = nil if self.time_signature == ''
begin
self[:jmep_json] = JmepManager.execute(self.jmep_text)
rescue ArgumentError => err
#errors.add(:jmep_text, err.to_s)
end
end
end

View File

@ -30,6 +30,8 @@ JamAdmin::Application.routes.draw do
match '/api/checks/latency_tester' => 'checks#check_latency_tester', :via => :get
match '/api/users/emailables/:code' => 'email#dump_emailables', :via => :get
match '/api/teachers/:code' => 'email#dump_teachers', :via => :get
match '/jam_tracks/top/:code' => 'jam_track#dump_top_selling', :via => :get
match '/api/jam_tracks/released' => 'jam_track#dump_released', :via => :get, as: 'released_jamtracks_csv'
mount Resque::Server.new, :at => "/resque"

View File

@ -3,4 +3,4 @@ source 'http://rubygems.org'
# Assumes you have already cloned pg_migrate_ruby in your workspace
# $ cd [workspace]
# $ git clone https://github.com/sethcall/pg_migrate_ruby
gem 'pg_migrate', '0.1.13', :source => 'http://rubygems.org/'
gem 'pg_migrate', '0.1.14', :source => 'http://rubygems.org/'

View File

@ -1,21 +1,21 @@
GEM
remote: http://rubygems.org/
specs:
little-plugger (1.1.3)
little-plugger (1.1.4)
logging (1.7.2)
little-plugger (>= 1.1.3)
pg (0.17.1)
pg_migrate (0.1.13)
pg_migrate (0.1.14)
logging (= 1.7.2)
pg (= 0.17.1)
thor
thor (0.18.1)
thor (0.19.1)
PLATFORMS
ruby
DEPENDENCIES
pg_migrate (= 0.1.13)!
pg_migrate (= 0.1.14)!
BUNDLED WITH
1.10.5
1.11.2

View File

@ -303,4 +303,61 @@ jam_track_name_drop_unique.sql
jam_track_searchability.sql
harry_fox_agency.sql
jam_track_slug.sql
rails4_migration.sql
mixdown.sql
aac_master.sql
video_recording.sql
web_playable_jamtracks.sql
affiliate_partner_rate.sql
track_downloads.sql
jam_track_lang_idx.sql
giftcard.sql
add_description_to_crash_dumps.sql
acappella.sql
purchasable_gift_cards.sql
versionable_jamtracks.sql
session_controller.sql
jam_tracks_bpm.sql
jam_track_sessions.sql
jam_track_sessions_v2.sql
email_screening.sql
bounced_email_cleanup.sql
news.sql
profile_teacher.sql
populate_languages.sql
populate_subjects.sql
reviews.sql
download_tracker_fingerprints.sql
connection_active.sql
chat_channel.sql
jamblaster.sql
test_drive_lessons.sql
whitelist.sql
teacher_student_flags.sql
add_sale_source_col.sql
jamblaster_v2.sql
acapella_rename.sql
jamblaster_pairing_active.sql
email_blacklist.sql
jamblaster_connection.sql
teacher_progression.sql
teacher_complete.sql
lessons.sql
lessons_unread_messages.sql
track_school_signups.sql
add_test_drive_types.sql
updated_subjects.sql
update_payment_history.sql
lesson_booking_schools.sql
lesson_booking_schools_2.sql
phantom_accounts.sql
lesson_booking_success.sql
user_origin.sql
remove_stripe_acct_id.sql
track_user_on_lesson.sql
audio_in_music_notations.sql
lesson_time_tracking.sql
packaged_test_drive.sql
packaged_test_drive2.sql
jamclass_report.sql
jamblasters_network.sql
rails4_migration.sql

3
db/up/aac_master.sql Normal file
View File

@ -0,0 +1,3 @@
ALTER TABLE jam_track_tracks ADD COLUMN preview_aac_url VARCHAR;
ALTER TABLE jam_track_tracks ADD COLUMN preview_aac_md5 VARCHAR;
ALTER TABLE jam_track_tracks ADD COLUMN preview_aac_length bigint;

View File

@ -0,0 +1,2 @@
UPDATE genres set description = 'A Cappella' where id = 'acapella';

2
db/up/acappella.sql Normal file
View File

@ -0,0 +1,2 @@
INSERT INTO genres (id, description) values ('acapella', 'A Capella');
ALTER TABLE jam_track_licensors ADD COLUMN slug VARCHAR UNIQUE;

View File

@ -0,0 +1 @@
ALTER TABLE crash_dumps ADD COLUMN description VARCHAR(20000);

View File

@ -0,0 +1 @@
ALTER TABLE sales ADD COLUMN source VARCHAR NOT NULL DEFAULT 'recurly';

View File

@ -0,0 +1,4 @@
INSERT INTO lesson_package_types (id, name, description, package_type, price) VALUES ('test-drive-2', 'Test Drive (2)', 'Two reduced-price lessons which you can use to find that ideal teacher.', 'test-drive-2', 29.99);
INSERT INTO lesson_package_types (id, name, description, package_type, price) VALUES ('test-drive-1', 'Test Drive (1)', 'One reduced-price lessons which you can use to find that ideal teacher.', 'test-drive-1', 15.99);
UPDATE lesson_package_types set name = 'Test Drive (4)', package_type = 'test-drive-4' WHERE id = 'test-drive';
ALTER TABLE users ADD COLUMN lesson_package_type_id VARCHAR(64) REFERENCES lesson_package_types(id);

View File

@ -15,7 +15,6 @@ CREATE TABLE admin_users (
updated_at timestamp without time zone NOT NULL
);
ALTER TABLE public.admin_users OWNER TO postgres;
CREATE SEQUENCE admin_users_id_seq
START WITH 1
INCREMENT BY 1
@ -23,7 +22,6 @@ CREATE SEQUENCE admin_users_id_seq
NO MAXVALUE
CACHE 1;
ALTER TABLE public.admin_users_id_seq OWNER TO postgres;
ALTER SEQUENCE admin_users_id_seq OWNED BY admin_users.id;
SELECT pg_catalog.setval('admin_users_id_seq', 2, true);
ALTER TABLE ONLY admin_users ALTER COLUMN id SET DEFAULT nextval('admin_users_id_seq'::regclass);
@ -45,7 +43,6 @@ CREATE TABLE active_admin_comments (
updated_at timestamp without time zone NOT NULL,
namespace character varying(255)
);
ALTER TABLE public.active_admin_comments OWNER TO postgres;
CREATE SEQUENCE active_admin_comments_id_seq
START WITH 1
INCREMENT BY 1
@ -53,7 +50,6 @@ CREATE SEQUENCE active_admin_comments_id_seq
NO MAXVALUE
CACHE 1;
ALTER TABLE public.active_admin_comments_id_seq OWNER TO postgres;
ALTER SEQUENCE active_admin_comments_id_seq OWNED BY active_admin_comments.id;
SELECT pg_catalog.setval('active_admin_comments_id_seq', 1, false);
ALTER TABLE ONLY active_admin_comments ALTER COLUMN id SET DEFAULT nextval('active_admin_comments_id_seq'::regclass);

View File

@ -0,0 +1 @@
ALTER TABLE affiliate_partners ADD COLUMN rate NUMERIC(8,2) DEFAULT 0.10;

View File

@ -0,0 +1,5 @@
ALTER TABLE music_notations ADD COLUMN attachment_type VARCHAR NOT NULL DEFAULT 'notation';
ALTER TABLE chat_messages ADD PRIMARY KEY (id);
ALTER TABLE music_notations ADD PRIMARY KEY (id);
ALTER TABLE chat_messages ADD COLUMN music_notation_id VARCHAR(64) REFERENCES music_notations(id);
ALTER TABLE chat_messages ADD COLUMN claimed_recording_id VARCHAR(64) REFERENCES claimed_recordings(id);

View File

@ -0,0 +1,3 @@
ALTER TABLE generic_state ADD COLUMN bounce_check_at DATE;
UPDATE generic_state SET bounce_check_at = NOW();
ALTER TABLE users ADD COLUMN bounced BOOLEAN DEFAULT FALSE;

4
db/up/chat_channel.sql Normal file
View File

@ -0,0 +1,4 @@
ALTER TABLE chat_messages ADD COLUMN channel VARCHAR(128) NOT NULL DEFAULT 'session';
CREATE INDEX chat_messages_idx_channels ON chat_messages(channel);
CREATE INDEX chat_messages_idx_created_at ON chat_messages(created_at);
CREATE INDEX chat_messages_idx_music_session_id ON chat_messages(music_session_id);

View File

@ -0,0 +1 @@
ALTER TABLE connections ADD COLUMN user_active BOOLEAN DEFAULT TRUE;

6
db/up/crash_dumps_2.sql Normal file
View File

@ -0,0 +1,6 @@
ALTER TABLE crash_dumps ADD COLUMN email VARCHAR(255);
ALTER TABLE crash_dumps ADD COLUMN description VARCHAR(10000);
ALTER TABLE crash_dumps ADD COLUMN os VARCHAR(100);
ALTER TABLE crash_dumps ADD COLUMN os_version VARCHAR(100);
ALTER TABLE crash_dumps DROP CONSTRAINT crash_dumps_user_id_fkey;

View File

@ -0,0 +1,3 @@
ALTER TABLE download_trackers ADD COLUMN fingerprint VARCHAR(1000);
CREATE INDEX index_download_trackers_on_fingerprint ON download_trackers USING btree (fingerprint);
ALTER TABLE download_trackers ADD COLUMN is_client BOOLEAN DEFAULT FALSE;

10
db/up/email_blacklist.sql Normal file
View File

@ -0,0 +1,10 @@
CREATE TABLE email_blacklists (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
email VARCHAR(1000) UNIQUE NOT NULL,
source VARCHAR(1000),
notes VARCHAR(1000),
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
);
ALTER TABLE jamblasters DROP COLUMN vtoken;

View File

@ -0,0 +1,2 @@
ALTER TABLE users ADD COLUMN email_needs_verification BOOLEAN DEFAULT FALSE;
ALTER TABLE users ADD COLUMN kickbox_response JSON;

13
db/up/giftcard.sql Normal file
View File

@ -0,0 +1,13 @@
CREATE TABLE gift_cards (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
code VARCHAR(64) UNIQUE NOT NULL,
user_id VARCHAR (64) REFERENCES users(id) ON DELETE CASCADE,
card_type VARCHAR(64) NOT NULL,
origin VARCHAR(200),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX gift_card_user_id_idx ON gift_cards(user_id);
ALTER TABLE users ADD COLUMN gifted_jamtracks INTEGER DEFAULT 0;

View File

@ -0,0 +1 @@
CREATE INDEX ON jam_tracks(language);

View File

@ -0,0 +1,9 @@
CREATE TABLE jam_track_sessions (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
jam_track_id VARCHAR(64) NOT NULL REFERENCES jam_tracks(id) ON DELETE CASCADE,
session_type VARCHAR(10) NOT NULL,
music_session_id VARCHAR(64) REFERENCES music_sessions(id) ON DELETE SET NULL,
user_id VARCHAR(64) NOT NULL REFERENCES users(id),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

View File

@ -0,0 +1,2 @@
ALTER TABLE jam_track_sessions ALTER COLUMN user_id DROP NOT NULL;
ALTER TABLE crash_dumps ALTER COLUMN user_id DROP NOT NULL;

2
db/up/jam_tracks_bpm.sql Normal file
View File

@ -0,0 +1,2 @@
ALTER TABLE jam_tracks ADD COLUMN bpm numeric(8,3);
INSERT INTO instruments (id, description) VALUES ('percussion', 'Percussion');

28
db/up/jamblaster.sql Normal file
View File

@ -0,0 +1,28 @@
CREATE TABLE jamblasters (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE SET NULL,
serial_no VARCHAR(1000) UNIQUE,
vtoken VARCHAR(1000) UNIQUE,
client_id VARCHAR(64) UNIQUE,
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
);
CREATE TABLE jamblasters_users (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
jamblaster_id VARCHAR(64) NOT NULL REFERENCES jamblasters(id) ON DELETE CASCADE,
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
);
CREATE TABLE jamblaster_pairing_requests (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
jamblaster_id VARCHAR(64) NOT NULL REFERENCES jamblasters(id) ON DELETE CASCADE,
jamblaster_client_id VARCHAR(64) NOT NULL,
sibling_client_id VARCHAR(64) NOT NULL,
sibling_key VARCHAR(1000) NOT NULL,
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
);

View File

@ -0,0 +1 @@
ALTER TABLE connections ADD COLUMN is_jamblaster BOOLEAN DEFAULT FALSE;

View File

@ -0,0 +1 @@
ALTER TABLE jamblaster_pairing_requests ADD COLUMN active BOOLEAN NOT NULL DEFAULT FALSE;

3
db/up/jamblaster_v2.sql Normal file
View File

@ -0,0 +1,3 @@
ALTER TABLE jamblaster_pairing_requests ALTER COLUMN sibling_key DROP NOT NULL;
ALTER TABLE jamblaster_pairing_requests ADD COLUMN vtoken VARCHAR(400) NOT NULL;
ALTER TABLE jamblaster_pairing_requests DROP COLUMN sibling_client_id;

View File

@ -0,0 +1,3 @@
ALTER TABLE jamblasters ADD COLUMN ipv6_link_local VARCHAR;
ALTER TABLE jamblasters ADD COLUMN ipv4_link_local VARCHAR;
ALTER TABLE jamblasters ADD COLUMN display_name VARCHAR;

33
db/up/jamclass_report.sql Normal file
View File

@ -0,0 +1,33 @@
CREATE TABLE campaign_spends (
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
campaign VARCHAR NOT NULL,
spend NUMERIC(8,2) NOT NULL,
month INTEGER NOT NULL,
year INTEGER NOT NULL,
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE jam_class_reports (
cohort DATE,
campaign VARCHAR,
spend NUMERIC (8,2),
registrations INTEGER,
td_customers INTEGER,
jamclass_rev NUMERIC (8,2),
td4 INTEGER,
td2 INTEGER,
td1 INTEGER,
spend_td NUMERIC (8,2),
purchases0 NUMERIC (8,2),
purchases1 NUMERIC (8,2),
purchases2 NUMERIC (8,2),
purchases3 NUMERIC (8,2),
purchases_rest NUMERIC (8,2),
purchases0_count INTEGER,
purchases1_count INTEGER,
purchases2_count INTEGER,
purchases3_count INTEGER,
purchases_rest_count INTEGER,
purchases_count INTEGER
);

View File

@ -0,0 +1,3 @@
ALTER TABLE lesson_bookings ADD COLUMN school_id INTEGER REFERENCES schools(id);
ALTER TABLE teacher_payments ADD COLUMN school_id INTEGER REFERENCES schools(id);
ALTER TABLE teacher_distributions ADD COLUMN school_id INTEGER REFERENCES schools(id);

View File

@ -0,0 +1,2 @@
ALTER TABLE lesson_bookings ADD COLUMN same_school BOOLEAN DEFAULT FALSE NOT NULL;
ALTER TABLE schools ADD COLUMN affiliate_partner_id INTEGER REFERENCES affiliate_partners(id);

View File

@ -0,0 +1 @@
ALTER TABLE lesson_bookings ADD COLUMN success BOOLEAN;

View File

@ -0,0 +1,6 @@
ALTER TABLE lesson_bookings ADD COLUMN sent_notices_at timestamp without time zone;
ALTER TABLE lesson_bookings ADD COLUMN countered_at timestamp without time zone;
ALTER TABLE lesson_sessions ADD COLUMN countered_at timestamp without time zone;
ALTER TABLE lesson_bookings ADD COLUMN counterer_id VARCHAR(64) REFERENCES users(id);
ALTER TABLE lesson_sessions ADD COLUMN counterer_id VARCHAR(64) REFERENCES users(id);
ALTER TABLE lesson_bookings ADD COLUMN sent_counter_reminder BOOLEAN NOT NULL DEFAULT FALSE;

261
db/up/lessons.sql Normal file
View File

@ -0,0 +1,261 @@
CREATE TABLE lesson_package_types (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR NOT NULL,
description VARCHAR NOT NULL,
package_type VARCHAR(64) NOT NULL,
price NUMERIC(8,2),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE lesson_bookings (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id VARCHAR(64) REFERENCES users(id) NOT NULL,
active BOOLEAN NOT NULL DEFAULT FALSE,
accepter_id VARCHAR(64) REFERENCES users(id),
canceler_id VARCHAR(64) REFERENCES users(id),
lesson_type VARCHAR(64) NOT NULL,
recurring BOOLEAN NOT NULL,
lesson_length INTEGER NOT NULL,
payment_style VARCHAR(64) NOT NULL,
description VARCHAR,
booked_price NUMERIC(8,2) NOT NULL,
teacher_id VARCHAR(64) REFERENCES users(id) NOT NULL,
card_presumed_ok BOOLEAN NOT NULL DEFAULT FALSE,
sent_notices BOOLEAN NOT NULL DEFAULT FALSE,
status VARCHAR,
cancel_message VARCHAR,
user_decremented BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE charges (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
amount_in_cents INTEGER NOT NULL,
fee_in_cents INTEGER NOT NULL DEFAULT 0,
type VARCHAR(64) NOT NULL,
sent_billing_notices BOOLEAN NOT NULL DEFAULT FALSE,
sent_billing_notices_at TIMESTAMP,
last_billing_attempt_at TIMESTAMP,
billed BOOLEAN NOT NULL DEFAULT FALSE,
billed_at TIMESTAMP,
post_processed BOOLEAN NOT NULL DEFAULT FALSE,
post_processed_at TIMESTAMP,
billing_error_reason VARCHAR,
billing_error_detail VARCHAR,
billing_should_retry BOOLEAN NOT NULL DEFAULT TRUE ,
billing_attempts INTEGER NOT NULL DEFAULT 0,
stripe_charge_id VARCHAR(200),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE lesson_package_purchases (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
lesson_package_type_id VARCHAR(64) REFERENCES lesson_package_types(id) NOT NULL,
user_id VARCHAR(64) REFERENCES users(id) NOT NULL,
teacher_id VARCHAR(64) REFERENCES users(id),
price NUMERIC(8,2),
recurring BOOLEAN NOT NULL DEFAULT FALSE,
year INTEGER,
month INTEGER,
charge_id VARCHAR(64) REFERENCES charges(id),
lesson_booking_id VARCHAR(64) REFERENCES lesson_bookings(id),
sent_notices BOOLEAN NOT NULL DEFAULT FALSE,
sent_notices_at TIMESTAMP,
post_processed BOOLEAN NOT NULL DEFAULT FALSE,
post_processed_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE lesson_sessions (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
lesson_type VARCHAR(64) NOT NULL,
teacher_id VARCHAR(64) REFERENCES users(id) NOT NULL,
lesson_package_purchase_id VARCHAR(64) REFERENCES lesson_package_purchases(id),
lesson_booking_id VARCHAR(64) REFERENCES lesson_bookings(id),
duration INTEGER NOT NULL,
booked_price NUMERIC(8,2) NOT NULL,
teacher_complete BOOLEAN DEFAULT FALSE NOT NULL,
student_complete BOOLEAN DEFAULT FALSE NOT NULL,
student_canceled BOOLEAN DEFAULT FALSE NOT NULL,
teacher_canceled BOOLEAN DEFAULT FALSE NOT NULL,
student_canceled_at TIMESTAMP,
teacher_canceled_at TIMESTAMP,
student_canceled_reason VARCHAR,
teacher_canceled_reason VARCHAR,
status VARCHAR,
analysed BOOLEAN NOT NULL DEFAULT FALSE,
analysis JSON,
analysed_at TIMESTAMP,
cancel_message VARCHAR,
canceler_id VARCHAR(64) REFERENCES users(id),
charge_id VARCHAR(64) REFERENCES charges(id),
success BOOLEAN NOT NULL DEFAULT FALSE,
sent_notices BOOLEAN NOT NULL DEFAULT FALSE,
sent_notices_at TIMESTAMP,
post_processed BOOLEAN NOT NULL DEFAULT FALSE,
post_processed_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE music_sessions ADD COLUMN lesson_session_id VARCHAR(64) REFERENCES lesson_sessions(id);
ALTER TABLE notifications ADD COLUMN lesson_session_id VARCHAR(64) REFERENCES lesson_sessions(id);
ALTER TABLE notifications ADD COLUMN purpose VARCHAR(200);
ALTER TABLE notifications ADD COLUMN student_directed BOOLEAN;
INSERT INTO lesson_package_types (id, name, description, package_type, price) VALUES ('single', 'Single Lesson', 'A single lesson purchased at the teacher''s price.', 'single', 0.00);
INSERT INTO lesson_package_types (id, name, description, package_type, price) VALUES ('single-free', 'Free Lesson', 'A free, single lesson.', 'single-free', 0.00);
INSERT INTO lesson_package_types (id, name, description, package_type, price) VALUES ('test-drive', 'Test Drive', 'Four reduced-price lessons which you can use to find that ideal teacher.', 'test-drive', 49.99);
CREATE TABLE lesson_booking_slots (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
lesson_booking_id VARCHAR(64) REFERENCES lesson_bookings(id),
lesson_session_id VARCHAR(64) REFERENCES lesson_sessions(id),
slot_type VARCHAR(64) NOT NULL,
preferred_day DATE,
day_of_week INTEGER,
hour INTEGER,
minute INTEGER,
timezone VARCHAR NOT NULL,
message VARCHAR,
accept_message VARCHAR,
update_all BOOLEAN NOT NULL DEFAULT FALSE,
proposer_id VARCHAR(64) REFERENCES users(id) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE lesson_bookings ADD COLUMN default_slot_id VARCHAR(64) REFERENCES lesson_booking_slots(id);
ALTER TABLE lesson_bookings ADD COLUMN counter_slot_id VARCHAR(64) REFERENCES lesson_booking_slots(id);
ALTER TABLE lesson_sessions ADD COLUMN counter_slot_id VARCHAR(64) REFERENCES lesson_booking_slots(id);
ALTER TABLE lesson_sessions ADD COLUMN slot_id VARCHAR(64) REFERENCES lesson_booking_slots(id);
ALTER TABLE chat_messages ADD COLUMN target_user_id VARCHAR(64) REFERENCES users(id);
ALTER TABLE chat_messages ADD COLUMN lesson_booking_id VARCHAR(64) REFERENCES lesson_bookings(id);
ALTER TABLE users ADD COLUMN remaining_free_lessons INTEGER NOT NULL DEFAULT 1;
ALTER TABLE users ADD COLUMN stored_credit_card BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE users ADD COLUMN remaining_test_drives INTEGER NOT NULL DEFAULT 0;
ALTER TABLE users ADD COLUMN stripe_token VARCHAR(200);
ALTER TABLE users ADD COLUMN stripe_customer_id VARCHAR(200);
ALTER TABLE users ADD COLUMN stripe_zip_code VARCHAR(200);
ALTER TABLE sales ADD COLUMN stripe_charge_id VARCHAR(200);
ALTER TABLE teachers ADD COLUMN stripe_account_id VARCHAR(200);
ALTER TABLE sale_line_items ADD COLUMN lesson_package_purchase_id VARCHAR(64) REFERENCES lesson_package_purchases(id);
-- one is created every time the teacher is paid. N teacher_distributions point to this
CREATE TABLE teacher_payments (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
teacher_id VARCHAR(64) REFERENCES users(id) NOT NULL,
charge_id VARCHAR(64) REFERENCES charges(id) NOT NULL,
amount_in_cents INTEGER NOT NULL,
fee_in_cents INTEGER NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- one is created for every bit of money the teacher is due
CREATE TABLE teacher_distributions (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
teacher_id VARCHAR(64) REFERENCES users(id) NOT NULL,
teacher_payment_id VARCHAR(64) REFERENCES teacher_payments(id),
lesson_session_id VARCHAR(64) REFERENCES lesson_sessions(id),
lesson_package_purchase_id VARCHAR(64) REFERENCES lesson_package_purchases(id),
amount_in_cents INTEGER NOT NULL,
ready BOOLEAN NOT NULL DEFAULT FALSE,
distributed BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE affiliate_distributions (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
affiliate_referral_id INTEGER REFERENCES affiliate_partners(id) NOT NULL,
affiliate_referral_fee_in_cents INTEGER NOT NULL,
sale_line_item_id VARCHAR(64) REFERENCES sale_line_items(id) NOT NULL,
affiliate_refunded BOOLEAN NOT NULL DEFAULT FALSE,
affiliate_refunded_at TIMESTAMP WITHOUT TIME ZONE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE affiliate_partners ADD COLUMN lesson_rate NUMERIC (8,2) NOT NULL DEFAULT 0.20;
-- move over all sale_line_item affiliate info
INSERT INTO affiliate_distributions (
SELECT
sale_line_items.id,
sale_line_items.affiliate_referral_id,
sale_line_items.affiliate_referral_fee_in_cents,
sale_line_items.id,
sale_line_items.affiliate_refunded,
sale_line_items.affiliate_refunded_at,
sale_line_items.created_at,
sale_line_items.updated_at
FROM sale_line_items
WHERE sale_line_items.affiliate_referral_id IS NOT NULL
);
CREATE TABLE teacher_intents (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id VARCHAR(64) REFERENCES users(id) NOT NULL,
teacher_id VARCHAR(64) REFERENCES teachers(id) NOT NULL,
intent VARCHAR(64),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX teacher_intents_intent_idx ON teacher_intents(teacher_id, intent);
CREATE TABLE schools (
id INTEGER PRIMARY KEY,
user_id VARCHAR(64) REFERENCES users(id) NOT NULL,
name VARCHAR,
enabled BOOLEAN DEFAULT TRUE,
scheduling_communication VARCHAR NOT NULL DEFAULT 'teacher',
correspondence_email VARCHAR,
photo_url VARCHAR(2048),
original_fpfile VARCHAR(8000),
cropped_fpfile VARCHAR(8000),
cropped_s3_path VARCHAR(8000),
crop_selection VARCHAR(256),
large_photo_url VARCHAR(512),
cropped_large_s3_path VARCHAR(512),
cropped_large_fpfile VARCHAR(8000),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE SEQUENCE school_key_sequence;
ALTER SEQUENCE school_key_sequence RESTART WITH 10000;
ALTER TABLE schools ALTER COLUMN id SET DEFAULT nextval('school_key_sequence');
ALTER TABLE users ADD COLUMN school_id INTEGER REFERENCES schools(id);
ALTER TABLE users ADD COLUMN joined_school_at TIMESTAMP;
ALTER TABLE teachers ADD COLUMN school_id INTEGER REFERENCES schools(id);
ALTER TABLE teachers ADD COLUMN joined_school_at TIMESTAMP;
CREATE TABLE school_invitations (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id VARCHAR(64) REFERENCES users(id),
school_id INTEGER REFERENCES schools(id) NOT NULL,
invitation_code VARCHAR(256) NOT NULL UNIQUE,
note VARCHAR,
as_teacher BOOLEAN NOT NULL,
email VARCHAR NOT NULL,
first_name VARCHAR,
last_name VARCHAR,
accepted BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE teachers ADD jamkazam_rate NUMERIC (8, 2) DEFAULT 0.25;
ALTER TABLE schools ADD jamkazam_rate NUMERIC (8, 2) DEFAULT 0.25;

View File

@ -0,0 +1,34 @@
ALTER TABLE chat_messages DROP COLUMN lesson_booking_id;
ALTER TABLE chat_messages ADD COLUMN lesson_session_id VARCHAR(64) REFERENCES lesson_sessions(id);
ALTER TABLE lesson_sessions ADD COLUMN teacher_unread_messages BOOLEAN DEFAULT FALSE NOT NULL;
ALTER TABLE lesson_sessions ADD COLUMN student_unread_messages BOOLEAN DEFAULT FALSE NOT NULL;
ALTER TABLE chat_messages ADD COLUMN purpose VARCHAR(200);
ALTER TABLE lesson_sessions ADD COLUMN student_short_canceled BOOLEAN DEFAULT FALSE NOT NULL;
ALTER TABLE lesson_sessions ADD COLUMN teacher_short_canceled BOOLEAN DEFAULT FALSE NOT NULL;
ALTER TABLE lesson_sessions ADD COLUMN sent_starting_notice BOOLEAN DEFAULT FALSE NOT NULL;
ALTER TABLE lesson_bookings DROP CONSTRAINT lesson_bookings_counter_slot_id_fkey;
ALTER TABLE lesson_bookings ADD CONSTRAINT lesson_bookings_counter_slot_id_fkey FOREIGN KEY (counter_slot_id) REFERENCES lesson_booking_slots(id) ON DELETE CASCADE;
ALTER TABLE lesson_bookings DROP CONSTRAINT lesson_bookings_default_slot_id_fkey;
ALTER TABLE lesson_bookings ADD CONSTRAINT lesson_bookings_default_slot_id_fkey FOREIGN KEY (default_slot_id) REFERENCES lesson_booking_slots(id) ON DELETE CASCADE;
ALTER TABLE lesson_sessions DROP CONSTRAINT lesson_sessions_slot_id_fkey;
ALTER TABLE lesson_sessions ADD CONSTRAINT lesson_sessions_slot_id_fkey FOREIGN KEY (slot_id) REFERENCES lesson_booking_slots(id) ON DELETE CASCADE;
ALTER TABLE users DROP CONSTRAINT users_teacher_id_fkey;
ALTER TABLE users ADD CONSTRAINT users_teacher_id_fkey FOREIGN KEY (teacher_id) REFERENCES teachers(id) ON DELETE CASCADE;
ALTER TABLE music_sessions DROP CONSTRAINT music_sessions_lesson_session_id_fkey;
ALTER TABLE music_sessions ADD CONSTRAINT music_sessions_lesson_session_id_fkey FOREIGN KEY (lesson_session_id) REFERENCES lesson_sessions(id) ON DELETE SET NULL;
ALTER TABLE notifications DROP CONSTRAINT notifications_lesson_session_id_fkey;
ALTER TABLE notifications ADD CONSTRAINT notifications_lesson_session_id_fkey FOREIGN KEY (lesson_session_id) REFERENCES lesson_sessions(id) ON DELETE CASCADE;
ALTER TABLE chat_messages DROP CONSTRAINT chat_messages_lesson_session_id_fkey;
ALTER TABLE chat_messages ADD CONSTRAINT chat_messages_lesson_session_id_fkey FOREIGN KEY (lesson_session_id) REFERENCES lesson_sessions(id) ON DELETE CASCADE;
ALTER TABLE chat_messages DROP CONSTRAINT chat_messages_target_user_id_fkey;
ALTER TABLE chat_messages ADD CONSTRAINT chat_messages_target_user_id_fkey FOREIGN KEY (lesson_session_id) REFERENCES lesson_sessions(id) ON DELETE SET NULL;

61
db/up/mixdown.sql Normal file
View File

@ -0,0 +1,61 @@
CREATE TABLE jam_track_mixdowns (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
jam_track_id VARCHAR(64) NOT NULL REFERENCES jam_tracks(id) ON DELETE CASCADE,
user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
settings JSON NOT NULL,
name VARCHAR(1000) NOT NULL,
description VARCHAR(1000),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE jam_track_mixdown_packages (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
jam_track_mixdown_id VARCHAR(64) NOT NULL REFERENCES jam_track_mixdowns(id) ON DELETE CASCADE,
file_type VARCHAR NOT NULL ,
sample_rate INTEGER NOT NULL,
url VARCHAR(2048),
md5 VARCHAR,
length INTEGER,
downloaded_since_sign BOOLEAN NOT NULL DEFAULT FALSE,
last_step_at TIMESTAMP,
last_signed_at TIMESTAMP,
download_count INTEGER NOT NULL DEFAULT 0,
signed_at TIMESTAMP,
downloaded_at TIMESTAMP,
signing_queued_at TIMESTAMP,
error_count INTEGER NOT NULL DEFAULT 0,
error_reason VARCHAR,
error_detail VARCHAR,
should_retry BOOLEAN NOT NULL DEFAULT FALSE,
packaging_steps INTEGER,
current_packaging_step INTEGER,
private_key VARCHAR,
signed BOOLEAN,
signing_started_at TIMESTAMP,
first_downloaded TIMESTAMP,
signing BOOLEAN NOT NULL DEFAULT FALSE,
encrypt_type VARCHAR,
first_downloaded_at TIMESTAMP,
last_downloaded_at TIMESTAMP,
version VARCHAR NOT NULL DEFAULT '1',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE jam_track_rights ADD COLUMN last_mixdown_id VARCHAR(64) REFERENCES jam_track_mixdowns(id) ON DELETE SET NULL;
ALTER TABLE notifications ADD COLUMN jam_track_mixdown_package_id VARCHAR(64) REFERENCES jam_track_mixdown_packages(id) ON DELETE CASCADE;
ALTER TABLE jam_track_mixdown_packages ADD COLUMN last_errored_at TIMESTAMP;
ALTER TABLE jam_track_mixdown_packages ADD COLUMN queued BOOLEAN DEFAULT FALSE;
ALTER TABLE jam_track_mixdown_packages ADD COLUMN speed_pitched BOOLEAN DEFAULT FALSE;
ALTER TABLE jam_track_rights ADD COLUMN queued BOOLEAN DEFAULT FALSE;
CREATE INDEX jam_track_rights_queued ON jam_track_rights(queued);
CREATE INDEX jam_track_rights_signing_queued ON jam_track_rights(signing_queued_at);
CREATE INDEX jam_track_rights_updated ON jam_track_rights(updated_at);
CREATE INDEX jam_track_mixdown_packages_queued ON jam_track_mixdown_packages(queued);
CREATE INDEX jam_track_mixdown_packages_signing_queued ON jam_track_mixdown_packages(signing_queued_at);
CREATE INDEX jam_track_mixdown_packages_updated ON jam_track_mixdown_packages(updated_at);

8
db/up/news.sql Normal file
View File

@ -0,0 +1,8 @@
CREATE TABLE news (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
title VARCHAR NOT NULL,
body VARCHAR NOT NULL,
position INTEGER NOT NULL UNIQUE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

View File

@ -0,0 +1,38 @@
CREATE TABLE test_drive_packages (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR UNIQUE NOT NULL,
package_type VARCHAR NOT NULL,
description VARCHAR,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE test_drive_package_teachers (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id VARCHAR(64) REFERENCES users(id) ON DELETE CASCADE,
test_drive_package_id VARCHAR(64) REFERENCES test_drive_packages(id) ON DELETE CASCADE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE lesson_bookings ADD COLUMN test_drive_package_id VARCHAR(64) REFERENCES test_drive_packages(id);
CREATE TABLE test_drive_package_choices (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
test_drive_package_id VARCHAR(64) REFERENCES test_drive_packages(id) ON DELETE CASCADE,
user_id VARCHAR(64) REFERENCES users(id) ON DELETE CASCADE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE test_drive_package_choice_teachers (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
test_drive_package_choice_id VARCHAR(64) REFERENCES test_drive_package_choices(id) ON DELETE CASCADE,
teacher_id VARCHAR(64) REFERENCES users(id) ON DELETE CASCADE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE teachers ADD COLUMN short_bio VARCHAR;
ALTER TABLE test_drive_package_teachers ADD COLUMN short_bio VARCHAR;

View File

@ -0,0 +1,2 @@
ALTER TABLE lesson_booking_slots ADD COLUMN from_package BOOL DEFAULT FALSE;
ALTER TABLE lesson_bookings ADD COLUMN test_drive_package_choice_id VARCHAR(64) REFERENCES test_drive_package_choices(id);

View File

@ -0,0 +1,16 @@
ALTER TABLE users ADD COLUMN phantom BOOLEAN DEFAULT FALSE NOT NULL;
CREATE OR REPLACE FUNCTION phantom_check() RETURNS TRIGGER
STRICT VOLATILE AS $$
BEGIN
-- Remember who changed the payroll when
NEW.phantom := (SELECT NEW.email ilike 'phantom+%@jamkazam.com');
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER phantom_update BEFORE INSERT OR UPDATE
ON users FOR EACH ROW EXECUTE PROCEDURE phantom_check(id);
UPDATE users set updated_at = NOW();

View File

@ -0,0 +1,72 @@
insert into languages(description, id) values ('English','EN');
insert into languages(description, id) values ('Afrikanns','AF');
insert into languages(description, id) values ('Albanian','SQ');
insert into languages(description, id) values ('Arabic','AR');
insert into languages(description, id) values ('Armenian','HY');
insert into languages(description, id) values ('Basque','EU');
insert into languages(description, id) values ('Bengali','BN');
insert into languages(description, id) values ('Bulgarian','BG');
insert into languages(description, id) values ('Catalan','CA');
insert into languages(description, id) values ('Cambodian','KM');
insert into languages(description, id) values ('Chinese (Mandarin)','ZH');
insert into languages(description, id) values ('Croation','HR');
insert into languages(description, id) values ('Czech','CS');
insert into languages(description, id) values ('Danish','DA');
insert into languages(description, id) values ('Dutch','NL');
insert into languages(description, id) values ('Estonian','ET');
insert into languages(description, id) values ('Fiji','FJ');
insert into languages(description, id) values ('Finnish','FI');
insert into languages(description, id) values ('French','FR');
insert into languages(description, id) values ('Georgian','KA');
insert into languages(description, id) values ('German','DE');
insert into languages(description, id) values ('Greek','EL');
insert into languages(description, id) values ('Gujarati','GU');
insert into languages(description, id) values ('Hebrew','HE');
insert into languages(description, id) values ('Hindi','HI');
insert into languages(description, id) values ('Hungarian','HU');
insert into languages(description, id) values ('Icelandic','IS');
insert into languages(description, id) values ('Indonesian','ID');
insert into languages(description, id) values ('Irish','GA');
insert into languages(description, id) values ('Italian','IT');
insert into languages(description, id) values ('Japanese','JA');
insert into languages(description, id) values ('Javanese','JW');
insert into languages(description, id) values ('Korean','KO');
insert into languages(description, id) values ('Latin','LA');
insert into languages(description, id) values ('Latvian','LV');
insert into languages(description, id) values ('Lithuanian','LT');
insert into languages(description, id) values ('Macedonian','MK');
insert into languages(description, id) values ('Malay','MS');
insert into languages(description, id) values ('Malayalam','ML');
insert into languages(description, id) values ('Maltese','MT');
insert into languages(description, id) values ('Maori','MI');
insert into languages(description, id) values ('Marathi','MR');
insert into languages(description, id) values ('Mongolian','MN');
insert into languages(description, id) values ('Nepali','NE');
insert into languages(description, id) values ('Norwegian','NO');
insert into languages(description, id) values ('Persian','FA');
insert into languages(description, id) values ('Polish','PL');
insert into languages(description, id) values ('Portuguese','PT');
insert into languages(description, id) values ('Punjabi','PA');
insert into languages(description, id) values ('Quechua','QU');
insert into languages(description, id) values ('Romanian','RO');
insert into languages(description, id) values ('Russian','RU');
insert into languages(description, id) values ('Samoan','SM');
insert into languages(description, id) values ('Serbian','SR');
insert into languages(description, id) values ('Slovak','SK');
insert into languages(description, id) values ('Slovenian','SL');
insert into languages(description, id) values ('Spanish','ES');
insert into languages(description, id) values ('Swahili','SW');
insert into languages(description, id) values ('Swedish ','SV');
insert into languages(description, id) values ('Tamil','TA');
insert into languages(description, id) values ('Tatar','TT');
insert into languages(description, id) values ('Telugu','TE');
insert into languages(description, id) values ('Thai','TH');
insert into languages(description, id) values ('Tibetan','BO');
insert into languages(description, id) values ('Tonga','TO');
insert into languages(description, id) values ('Turkish','TR');
insert into languages(description, id) values ('Ukranian','UK');
insert into languages(description, id) values ('Urdu','UR');
insert into languages(description, id) values ('Uzbek','UZ');
insert into languages(description, id) values ('Vietnamese','VI');
insert into languages(description, id) values ('Welsh','CY');
insert into languages(description, id) values ('Xhosa','XH');

View File

@ -0,0 +1,6 @@
insert into subjects(id, description) values ('arranging', 'Arranging');
insert into subjects(id, description) values ('composing', 'Composing');
insert into subjects(id, description) values ('music-business', 'Music Business');
insert into subjects(id, description) values ('music-theory', 'Music Theory');
insert into subjects(id, description) values ('recording', 'Recording');
insert into subjects(id, description) values ('site-reading', 'Site Reading');

75
db/up/profile_teacher.sql Normal file
View File

@ -0,0 +1,75 @@
CREATE TABLE teachers (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
introductory_video VARCHAR(1024) NULL,
years_teaching SMALLINT NOT NULL DEFAULT 0,
years_playing SMALLINT NOT NULL DEFAULT 0,
teaches_age_lower SMALLINT NOT NULL DEFAULT 0,
teaches_age_upper SMALLINT NOT NULL DEFAULT 0,
teaches_beginner BOOLEAN NOT NULL DEFAULT FALSE,
teaches_intermediate BOOLEAN NOT NULL DEFAULT FALSE,
teaches_advanced BOOLEAN NOT NULL DEFAULT FALSE,
website VARCHAR(1024) NULL,
biography VARCHAR(4096) NULL,
prices_per_lesson BOOLEAN NOT NULL DEFAULT FALSE,
prices_per_month BOOLEAN NOT NULL DEFAULT FALSE,
lesson_duration_30 BOOLEAN NOT NULL DEFAULT FALSE,
lesson_duration_45 BOOLEAN NOT NULL DEFAULT FALSE,
lesson_duration_60 BOOLEAN NOT NULL DEFAULT FALSE,
lesson_duration_90 BOOLEAN NOT NULL DEFAULT FALSE,
lesson_duration_120 BOOLEAN NOT NULL DEFAULT FALSE,
price_per_lesson_30_cents INT NULL,
price_per_lesson_45_cents INT NULL,
price_per_lesson_60_cents INT NULL,
price_per_lesson_90_cents INT NULL,
price_per_lesson_120_cents INT NULL,
price_per_month_30_cents INT NULL,
price_per_month_45_cents INT NULL,
price_per_month_60_cents INT NULL,
price_per_month_90_cents INT NULL,
price_per_month_120_cents INT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE users ADD COLUMN teacher_id VARCHAR(64) REFERENCES teachers(id) ON DELETE SET NULL;
CREATE TABLE subjects(
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
description VARCHAR(1024) NULL
);
CREATE TABLE languages(
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
description VARCHAR(1024) NULL
);
-- Has many:
CREATE TABLE teacher_experiences(
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
teacher_id VARCHAR(64) REFERENCES teachers(id) ON DELETE CASCADE,
-- experience type: teaching, education, award:
experience_type VARCHAR(32) NOT NULL,
name VARCHAR(200) NOT NULL,
organization VARCHAR(200) NOT NULL,
start_year SMALLINT NOT NULL DEFAULT 0,
end_year SMALLINT NULL
);
-- Has many/through tables:
CREATE TABLE teachers_genres(
teacher_id VARCHAR(64) REFERENCES teachers(id) ON DELETE CASCADE,
genre_id VARCHAR(64) REFERENCES genres(id) ON DELETE CASCADE
);
CREATE TABLE teachers_instruments(
teacher_id VARCHAR(64) REFERENCES teachers(id) ON DELETE CASCADE,
instrument_id VARCHAR(64) REFERENCES instruments(id) ON DELETE CASCADE
);
CREATE TABLE teachers_subjects(
teacher_id VARCHAR(64) REFERENCES teachers(id) ON DELETE CASCADE,
subject_id VARCHAR(64) REFERENCES subjects(id) ON DELETE CASCADE
);
CREATE TABLE teachers_languages(
teacher_id VARCHAR(64) REFERENCES teachers(id) ON DELETE CASCADE,
language_id VARCHAR(64) REFERENCES languages(id) ON DELETE CASCADE
);

View File

@ -0,0 +1,24 @@
CREATE TABLE gift_card_types (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
card_type VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO gift_card_types (id, card_type) VALUES ('jam_tracks_5', 'jam_tracks_5');
INSERT INTO gift_card_types (id, card_type) VALUES ('jam_tracks_10', 'jam_tracks_10');
CREATE TABLE gift_card_purchases (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE SET NULL,
gift_card_type_id VARCHAR(64) REFERENCES gift_card_types(id) ON DELETE SET NULL,
recurly_adjustment_uuid VARCHAR(500),
recurly_adjustment_credit_uuid VARCHAR(500),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE sale_line_items ADD COLUMN gift_card_purchase_id VARCHAR(64) REFERENCES gift_card_purchases(id);

View File

@ -0,0 +1 @@
ALTER TABLE teachers DROP COLUMN stripe_account_id;

23
db/up/reviews.sql Normal file
View File

@ -0,0 +1,23 @@
CREATE TABLE reviews (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
target_id VARCHAR(64) NOT NULL,
target_type VARCHAR(32) NOT NULL,
description VARCHAR,
rating INT NOT NULL,
deleted_by_user_id VARCHAR(64) REFERENCES users(id) ON DELETE SET NULL,
deleted_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NULL,
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
);
CREATE TABLE review_summaries (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
target_id VARCHAR(64) NOT NULL,
target_type VARCHAR(32) NOT NULL,
avg_rating FLOAT NOT NULL,
wilson_score FLOAT NOT NULL,
review_count INT NOT NULL,
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
);

Some files were not shown because too many files have changed in this diff Show More