-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Join affiliates with owners #118
base: master
Are you sure you want to change the base?
Changes from all commits
9026ae7
e156c5b
5dc53eb
c438343
68ba3c9
fde8f2c
05257c4
6e2f677
8e5a51c
cb7509c
fdcfc2a
62ce883
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -9,22 +9,23 @@ class Owner < ApplicationRecord | |||||
:confirmable, :recoverable, jwt_revocation_strategy: JwtDenylist | ||||||
|
||||||
validates :email, uniqueness: true, presence: true | ||||||
validates :password, | ||||||
presence: true, | ||||||
length: { in: Devise.password_length }, | ||||||
confirmation: true, | ||||||
on: :create | ||||||
|
||||||
validates :password, | ||||||
allow_nil: true, | ||||||
length: { in: Devise.password_length }, | ||||||
confirmation: true, | ||||||
validates :password, | ||||||
presence: true, | ||||||
length: { in: Devise.password_length }, | ||||||
confirmation: true, | ||||||
on: :create | ||||||
|
||||||
validates :password, | ||||||
allow_nil: true, | ||||||
length: { in: Devise.password_length }, | ||||||
confirmation: true, | ||||||
on: :update | ||||||
|
||||||
scope :affiliate, -> { where.not(affiliate: [nil, '']).order(affiliate: :asc) } | ||||||
scope :with_stripe_data, -> { where.not(stripe_subscription_id: nil) } | ||||||
|
||||||
belongs_to :frontend | ||||||
belongs_to :affiliate, optional: true | ||||||
|
||||||
has_many :companies, dependent: :destroy | ||||||
has_many :areas, through: :companies | ||||||
|
@@ -50,8 +51,7 @@ def blocked? | |||||
|
||||||
def affiliate_logo | ||||||
return unless affiliate | ||||||
|
||||||
Affiliate.find_by(code: affiliate)&.logo_url | ||||||
affiliate.logo_url | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
In case you have not seen before, it's called the safe navigation operator and makes sure we do not get an exception when affiliate is nil here :) |
||||||
end | ||||||
|
||||||
def frontend_url | ||||||
|
@@ -74,8 +74,7 @@ def stripe_price_id | |||||
main_price_id = ENV['STRIPE_SUBSCRIPTION_PRICE_ID'] | ||||||
|
||||||
raise "ENV['STRIPE_SUBSCRIPTION_PRICE_ID'] is empty" unless main_price_id.present? | ||||||
|
||||||
Affiliate.find_by(code: affiliate)&.stripe_price_id_monthly || main_price_id | ||||||
affiliate.stripe_price_id_monthly || main_price_id | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Elsewise this will also crash for empty affiliates |
||||||
end | ||||||
|
||||||
def stripe_subscription | ||||||
|
@@ -106,4 +105,9 @@ def trial_end | |||||
# There is not trial if the trial is blank or has already been passed, else it has to be at least two days in the future | ||||||
trial_ends_at? && trial_ends_at.future? ? [trial_ends_at, 50.hours.from_now].max.to_i : nil | ||||||
end | ||||||
|
||||||
def self.non_associated_affiliates | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be a scope instead of a class method, then one can also chain this, e.g.:
Perhaps a better name for this scope would then also be "with_missing_affiliate" or similar |
||||||
# To identify owners that have used an affiliate thats not properly registered in the affiliates table. | ||||||
Owner.where(affiliate: nil).where.not(affiliate_code: nil) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can actually leave the |
||||||
end | ||||||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
class ChangeAffiliateColumnName < ActiveRecord::Migration[6.1] | ||
def change | ||
rename_column :owners, :affiliate, :affiliate_code | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
class AddAffiliateRefToOwners < ActiveRecord::Migration[6.1] | ||
def change | ||
add_reference :owners, :affiliate, foreign_key: true, type: :uuid | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
owners_with_affiliate = Owner.all.select { |owner| owner.affiliate_code } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be a rake task :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can be written as a db query. Right now you first load all owners from the database to an array, and then filter it. This operation can be done way more efficiently by the database using the active record query interface. In this case one might use: |
||
|
||
owners_with_affiliate.each do |owner| | ||
matching_affiliate = Affiliate.find_by(code: owner.affiliate_code) | ||
if matching_affiliate | ||
owner.affiliate = matching_affiliate | ||
owner.save! | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,27 @@ | ||
# This file should contain all the record creation needed to seed the database with its default values. | ||
# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). | ||
# | ||
# Examples: | ||
# | ||
# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) | ||
# Character.create(name: 'Luke', movie: movies.first) | ||
Affiliate.destroy_all | ||
Owner.destroy_all | ||
|
||
7.times do | ||
FactoryBot.create(:affiliate) | ||
end | ||
affiliates = Affiliate.all | ||
affiliates.each { |affiliate| puts "#{affiliate.name} #{affiliate.code}" } | ||
|
||
20.times do | ||
FactoryBot.create(:owner) | ||
end | ||
owners = Owner.all | ||
owners.each { |owner| puts owner.name } | ||
|
||
|
||
# give 9 owners an affilate | ||
owners_with_affiliates = owners[0..8] | ||
owners_with_affiliates.each do |owner| | ||
owner.update!(affiliate_code: affiliates.sample.code) | ||
end | ||
|
||
# give 3 owners affiliates which are not yet entities in the db | ||
owners_with_other_affiliates = owners[9..11] | ||
owners_with_other_affiliates.each do |owner| | ||
owner.update!(affiliate_code: affiliates.sample.code.prepend('a').chop) | ||
end | ||
Comment on lines
+1
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should go into a spec (probably |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now, when migrating, we are going through three stages:
owner.affiliate
will return a string.affiliate
to return a model, but it's always empty. If payments are executed in this period, owners with affiliates might pay the full price, or similar weird behaviour might occur.affilaite
will return the affilaite modelSo I think for the transition it might make sense to overwrite the
owner.affiliate
method so it always returns the affiliate model. Something like