Skip to content
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

NVK-79 add webhook events to database table for debugging #144

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .yarn/install-state.gz
Binary file not shown.
4 changes: 4 additions & 0 deletions app/lib/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,9 @@ def check_subscription
puts ""
end
end

def deleted_old_webhook_events
ChargebeeEvent.where("created_at < ?", 3.months.ago).delete_all
end
end
end
59 changes: 39 additions & 20 deletions app/lib/webhook_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,35 @@
class WebhookHandler
class << self
def handle_payload(event)
cb_event = ChargebeeEvent.new(
event_id: event.id,
created_at: event.occurred_at,
event_type: event.event_type,
user_email: event.content.customer.email,
content: event.content
)
unless cb_event.save
Rails.logger.error("ChargebeeEvent failed: #{cb_event.errors.messages}")
return false
end

user = find_user(event)
if need_user(event) && !user
Rails.logger.error("User not found for #{event.content.customer.email}")
return true
end

case event.event_type
# when "payment_succeeded"
# upgrade_monthly_user(event)
# upgrade_monthly_user(user, event)
when "subscription_cancelled"
deactivate_user(event)
deactivate_user(user)
when "subscription_changed"
subscription_change(event)
subscription_change(user, event)
when "subscription_created"
subscription_create(event)
when "subscription_paused"
deactivate_user(event)
deactivate_user(user)
# when "subscription_reactivated"
# activate_user(event)
# when "subscription_resumed"
Expand All @@ -25,14 +43,17 @@ def handle_payload(event)

private

def activate_user(event)
def find_user(event)
customer = event.content.customer
user = User.find_by(cb_customer_id: customer.id)
unless user
Rails.logger.error("User not found for #{customer.id}")
return
end
User.find_by(cb_customer_id: customer.id)
end

# events that need a user for an update
def need_user(event)
event.event_type != "subscription_created"
end

def activate_user(user, event)
active = Util.subscription_is_annual_or_founding(event.content.subscription)

user.send_welcome_email if active && Rails.configuration.x.user_creation_send_email
Expand All @@ -41,23 +62,21 @@ def activate_user(event)
user.save
end

def deactivate_user(event)
customer = event.content.customer
user = User.find_by(cb_customer_id: customer.id)
return true unless user

def deactivate_user(user)
user.active = false
user.save
end

def subscription_change(event)
def subscription_change(user, event)
if Util.subscription_is_annual_or_founding(event.content.subscription)
activate_user(event)
user = find_user(event)
activate_user(user, event)
else
deactivate_user(event)
deactivate_user(user)
end
end

# TODO: handle creation for existing user
def subscription_create(event)
active = Util.subscription_is_annual_or_founding(event.content.subscription)

Expand All @@ -83,11 +102,11 @@ def subscription_create(event)
end
end

def upgrade_monthly_user(event)
def upgrade_monthly_user(user, event)
return true if Util.subscription_is_annual_or_founding(event.content.subscription)
started_at = event.content.subscription.started_at
if 2.years.ago.to_i > started_at
activate_user(event)
activate_user(user)
end
end
end
Expand Down
9 changes: 4 additions & 5 deletions app/models/artwork.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@ class Artwork < ApplicationRecord

MAX_ARTWORK_IMAGES = 3

MEDIUM_LIST = [ "Painting", "Photography", "Sculpture", "Prints", "Work on Paper", "NFT",
"Design", "Drawing", "Installation", "Film/Video", "Jewelry", "Performance Art",
"Reproduction", "Ephemera or Merchandise", "Digital Art"
]
MEDIUM_LIST = ["Painting", "Photography", "Sculpture", "Prints", "Work on Paper", "NFT",
"Design", "Drawing", "Installation", "Film/Video", "Jewelry", "Performance Art",
"Reproduction", "Ephemera or Merchandise", "Digital Art"]

validates :title, :medium, :location, :year, presence: true
validates :units, inclusion: {in: %w[in cm],
message: "%{value} is not a valid unit"}
validates :duration, numericality: {greater_than_or_equal_to: 0, allow_blank: true}
validates :price, numericality: {greater_than_or_equal_to: 0, allow_blank: true}
validates :year, numericality: {greater_than_or_equal_to: 1900}
validates :medium, inclusion: { in: MEDIUM_LIST}
validates :medium, inclusion: {in: MEDIUM_LIST}

belongs_to :user
positioned on: :user
Expand Down
2 changes: 2 additions & 0 deletions app/models/chargebee_event.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class ChargebeeEvent < ApplicationRecord
end
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
resources :artworks do
member do
patch :move_artwork
end
end
resources :images do
member do
patch :move_image
Expand Down
13 changes: 13 additions & 0 deletions db/migrate/20250209185340_add_chargebee_events.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class AddChargebeeEvents < ActiveRecord::Migration[7.2]
def change
create_table :chargebee_events, id: false do |t|
t.string :event_id, null: false
t.datetime :created_at, null: false, index: true
t.string :event_type, null: false, index: true
t.string :user_email, null: false, index: true
t.jsonb :content
end
add_index :chargebee_events, :event_id, unique: true
add_index :chargebee_events, :content, using: :gin, name: :chargebee_events_idx
end
end
16 changes: 15 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions lib/tasks/chargebee.rake
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@ namespace :chargebee do
task check_sub: :environment do
Util.check_subscription
end

desc "delete old webhook events"
task deleted_old_webhook_events: :environment do
Util.deleted_old_webhook_events
end
end
113 changes: 113 additions & 0 deletions test/fixtures/files/subscription_pause_scheduled.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
{
"id": "ev_AzqaRuUU8ubk53HJU",
"occurred_at": 1731622754,
"source": "admin_console",
"user": "[email protected]",
"object": "event",
"api_version": "v2",
"content": {
"subscription": {
"id": "2509882",
"billing_period": 1,
"billing_period_unit": "year",
"customer_id": "I-G3SKKUXLBL1B",
"status": "active",
"current_term_start": 1701208389,
"current_term_end": 1732830789,
"next_billing_at": 1740718800,
"created_at": 1669672389,
"started_at": 1669672389,
"activated_at": 1669672389,
"created_from_ip": "54.88.235.200",
"updated_at": 1731622754,
"has_scheduled_changes": false,
"channel": "web",
"resource_version": 1731622754615,
"deleted": false,
"object": "subscription",
"currency_code": "USD",
"subscription_items": [
{
"item_price_id": "Netvvrk-Annual-USD-Yearly",
"item_type": "plan",
"quantity": 1,
"unit_price": 79000,
"amount": 79000,
"free_quantity": 0,
"object": "subscription_item"
}
],
"shipping_address": {
"first_name": "Jane",
"last_name": "Bauman",
"email": "[email protected]",
"validation_status": "not_validated",
"object": "shipping_address"
},
"due_invoices_count": 0,
"mrr": 6583,
"exchange_rate": 1.0,
"base_currency_code": "USD",
"cf_Paypal_Migrated": "YES",
"pause_date": 1732830789,
"resume_date": 1740718800,
"has_scheduled_advance_invoices": false
},
"customer": {
"id": "I-G3SKKUXLBL1B",
"first_name": "Jane",
"last_name": "Bauman",
"email": "[email protected]",
"auto_collection": "off",
"net_term_days": 0,
"allow_direct_debit": false,
"created_at": 1699042118,
"created_from_ip": "27.5.153.91",
"taxability": "taxable",
"updated_at": 1712338306,
"pii_cleared": "active",
"channel": "web",
"resource_version": 1712338306433,
"deleted": false,
"object": "customer",
"billing_address": {
"country": "US",
"validation_status": "not_validated",
"object": "billing_address"
},
"card_status": "no_card",
"promotional_credits": 0,
"refundable_credits": 0,
"excess_payments": 0,
"unbilled_charges": 0,
"preferred_currency_code": "USD",
"mrr": 0,
"cf_Migrated": "YES",
"cf_Paypal": "YES"
}
},
"event_type": "subscription_pause_scheduled",
"webhook_status": "not_applicable",
"webhooks": [
{
"id": "whv2_16BdjQTta98S3V6B",
"webhook_status": "not_applicable",
"object": "webhook"
},
{
"id": "whv2_169lseTrjW9lv3Dj8",
"webhook_status": "succeeded",
"object": "webhook"
},
{
"id": "whv2_AzylISTta6fjqU6v",
"webhook_status": "not_applicable",
"object": "webhook"
},
{
"id": "whv2_AzyhBKU6RPt8W1gF7",
"webhook_status": "not_applicable",
"object": "webhook"
}
]
}
6 changes: 4 additions & 2 deletions test/lib/webhook_handler_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ class WebhookHandlerTest < ActiveSupport::TestCase
payload = File.read(Rails.root.join("test", "fixtures", "files", "subscription_created_annual.json"))
event = ChargeBee::Event.deserialize(payload)

assert_difference "User.count" do
assert WebhookHandler.handle_payload(event)
assert_difference "ChargebeeEvent.count", 1 do
assert_difference "User.count" do
assert WebhookHandler.handle_payload(event)
end
end
end

Expand Down