diff --git a/app/views/mailers/account_mailer/cancellation.html.erb b/app/views/mailers/account_mailer/cancellation.html.erb
index 831a1cdab..48c4a57b8 100644
--- a/app/views/mailers/account_mailer/cancellation.html.erb
+++ b/app/views/mailers/account_mailer/cancellation.html.erb
@@ -4,9 +4,6 @@
- No one can access the account anymore
- <% if @account.try(:subscription) %>
- - We won't charge you anymore
- <% end %>
- Everything in the account will be deleted in <%= distance_of_time_in_words_to_now(Account::Incineratable::INCINERATION_GRACE_PERIOD.from_now) %>
diff --git a/app/views/mailers/account_mailer/cancellation.text.erb b/app/views/mailers/account_mailer/cancellation.text.erb
index 3cfaf2689..b99364f32 100644
--- a/app/views/mailers/account_mailer/cancellation.text.erb
+++ b/app/views/mailers/account_mailer/cancellation.text.erb
@@ -3,9 +3,6 @@ Your Fizzy account "<%= @account.name %>" was cancelled.
WHAT HAPPENS NOW?
- No one can access the account anymore
-<% if @account.try(:subscription) %>
-- We won't charge you anymore
-<% end %>
- Everything in the account will be deleted in <%= distance_of_time_in_words_to_now(Account::Incineratable::INCINERATION_GRACE_PERIOD.from_now) %>
CHANGED YOUR MIND?
diff --git a/saas/app/models/account/queenbee_integration.rb b/saas/app/models/account/queenbee_integration.rb
new file mode 100644
index 000000000..3fa5333ca
--- /dev/null
+++ b/saas/app/models/account/queenbee_integration.rb
@@ -0,0 +1,58 @@
+module Account::QueenbeeIntegration
+ extend ActiveSupport::Concern
+
+ include Queenbee::Client
+
+ class_methods do
+ def find_by_queenbee_id(id)
+ find_by(external_account_id: id)
+ end
+ end
+
+ def queenbee_id
+ external_account_id
+ end
+
+ def cancel!
+ cancel(initiated_by: system_user)
+ end
+
+ def uncancel!
+ reactivate
+ end
+
+ def deactivate!
+ cancel!
+ end
+
+ def reactivate!
+ reactivate
+ end
+
+ def canceled?
+ cancelled?
+ end
+
+ def owner_name
+ users.owner.first&.name
+ end
+
+ def owner_email
+ users.owner.first&.identity&.email_address
+ end
+
+ def transferred_ownership!
+ raise NotImplementedError, "Fizzy does not support Queenbee-initiated ownership transfers"
+ end
+
+ def plan
+ "FreeV1"
+ end
+
+ def comped?
+ false
+ end
+
+ def comped=(value)
+ end
+end
diff --git a/saas/lib/fizzy/saas/engine.rb b/saas/lib/fizzy/saas/engine.rb
index 673be1147..1b967b1d5 100644
--- a/saas/lib/fizzy/saas/engine.rb
+++ b/saas/lib/fizzy/saas/engine.rb
@@ -133,7 +133,7 @@ module Fizzy
end
config.to_prepare do
- ::Account.include Account::StorageLimited
+ ::Account.include Account::QueenbeeIntegration, Account::StorageLimited
::Identity.include Authorization::Identity, Identity::Devices
::Session.include Session::Devices
::Signup.prepend Signup
diff --git a/saas/test/models/account/queenbee_integration_test.rb b/saas/test/models/account/queenbee_integration_test.rb
new file mode 100644
index 000000000..751e28b54
--- /dev/null
+++ b/saas/test/models/account/queenbee_integration_test.rb
@@ -0,0 +1,70 @@
+require "test_helper"
+require "queenbee/testing/client"
+
+class Account::QueenbeeIntegrationTest < ActiveSupport::TestCase
+ include Queenbee::Testing::Client
+
+ # Fizzy creates accounts via its own Signup flow (Fizzy → Queenbee),
+ # not via Queenbee pushing to Fizzy, so create_with_dependents is N/A.
+ undef_method :test_client_class_should_respond_to_create_with_dependents
+
+ setup do
+ @account = accounts(:"37s")
+ end
+
+ test "find_by_queenbee_id looks up by external_account_id" do
+ assert_equal @account, Account.find_by_queenbee_id(@account.external_account_id)
+ end
+
+ test "queenbee_id returns external_account_id" do
+ assert_equal @account.external_account_id, @account.queenbee_id
+ end
+
+ test "cancel! creates cancellation attributed to system user" do
+ @account.cancel!
+
+ assert @account.cancelled?
+ assert_equal @account.system_user, @account.cancellation.initiated_by
+ end
+
+ test "cancel! is idempotent" do
+ @account.cancel!
+ assert_no_difference -> { Account::Cancellation.count } do
+ @account.cancel!
+ end
+ end
+
+ test "cancel and reactivate round-trips" do
+ @account.cancel!
+ assert_not @account.active?
+
+ @account.reactivate!
+ @account.reload
+ assert @account.active?
+ end
+
+ test "deactivate! cancels the account" do
+ @account.deactivate!
+ assert @account.cancelled?
+ end
+
+ test "owner_name and owner_email from account owner" do
+ assert_equal users(:jason).name, @account.owner_name
+ assert_equal "jason@37signals.com", @account.owner_email
+ end
+
+ test "comped= is a no-op" do
+ @account.comped = true
+ assert_not @account.comped?
+ end
+
+ test "transferred_ownership! raises NotImplementedError" do
+ assert_raises(NotImplementedError) { @account.transferred_ownership! }
+ end
+
+ test "qb_serializable_hash includes queenbee_id and subscription" do
+ hash = @account.qb_serializable_hash
+ assert_equal @account.external_account_id, hash[:id]
+ assert_equal({ quantity: 1 }, hash[:subscription])
+ end
+end