Create offline_transaction_dispute.* event publishing

This commit is contained in:
Clarissa Borges 2021-04-12 12:43:23 -05:00 committed by Eric Schultz
parent 7972ec8ea7
commit a7cbf3653e
7 changed files with 409 additions and 9 deletions

View file

@ -163,6 +163,18 @@ class ObjectEventListener < ApplicationListener
enqueue_transmissions_to_webhooks(event)
end
def self.offline_transaction_dispute_created(event)
enqueue_transmissions_to_webhooks(event)
end
def self.offline_transaction_dispute_updated(event)
enqueue_transmissions_to_webhooks(event)
end
def self.offline_transaction_dispute_deleted(event)
enqueue_transmissions_to_webhooks(event)
end
private
def self.enqueue_transmissions_to_webhooks(event)

View file

@ -0,0 +1,96 @@
# frozen_string_literal: true
# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE
class OfflineTransactionDispute < ApplicationRecord
include Model::SubtransactionPaymentable
belongs_to :payment
delegate :gross_amount, :net_amount, :fee_total, to: :payment
delegate :currency, to: :nonprofit
# rubocop:disable Metrics/BlockLength
concerning :JBuilder do
included do
setup_houid :offtrxdspt
end
# rubocop:disable Metrics/AbcSize
def to_builder(*expand)
init_builder(*expand) do |json|
json.object 'offline_transaction_dispute'
json.gross_amount do
json.cents gross_amount
json.currency currency
end
json.net_amount do
json.cents net_amount
json.currency currency
end
json.fee_total do
json.cents fee_total
json.currency currency
end
json.created payment.date.to_i
json.type 'payment'
json.add_builder_expansion :nonprofit, :supporter, :subtransaction
json.add_builder_expansion :trx, json_attribute: :transaction
end
end
# rubocop:enable Metrics/AbcSize
def to_id
::Jbuilder.new do |json|
json.(self, :id)
json.object 'offline_transaction_dispute'
json.type 'payment'
end
end
def publish_created
Houdini.event_publisher.announce(
:offline_transaction_dispute_created,
to_event('offline_transaction_dispute.created',
:nonprofit,
:trx,
:supporter,
:subtransaction).attributes!
)
Houdini.event_publisher.announce(
:payment_created,
to_event('payment.created',
:nonprofit,
:trx,
:supporter,
:subtransaction).attributes!
)
end
def publish_updated
Houdini.event_publisher.announce(
:offline_transaction_dispute_updated,
to_event('offline_transaction_dispute.updated', :nonprofit, :trx, :supporter, :subtransaction).attributes!
)
Houdini.event_publisher.announce(
:payment_updated,
to_event('payment.updated', :nonprofit, :trx, :supporter, :subtransaction).attributes!
)
end
def publish_deleted
Houdini.event_publisher.announce(
:offline_transaction_dispute_deleted,
to_event('offline_transaction_dispute.deleted', :nonprofit, :trx, :supporter, :subtransaction).attributes!
)
Houdini.event_publisher.announce(
:payment_deleted,
to_event('payment.deleted', :nonprofit, :trx, :supporter, :subtransaction).attributes!
)
end
end
# rubocop:enable Metrics/BlockLength
end

View file

@ -13,7 +13,8 @@ class SubtransactionPayment < ApplicationRecord
has_one :supporter, through: :subtransaction
has_one :nonprofit, through: :subtransaction
delegated_type :paymentable, types: %w[OfflineTransactionCharge StripeCharge OfflineTransactionRefund]
delegated_type :paymentable,
types: %w[OfflineTransactionCharge StripeCharge OfflineTransactionRefund OfflineTransactionDispute]
delegate :gross_amount, :fee_total, :net_amount, to: :paymentable

View file

@ -0,0 +1,13 @@
# frozen_string_literal: true
# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE
class CreateOfflineTransactionDisputes < ActiveRecord::Migration[6.1]
def change
create_table :offline_transaction_disputes, id: :string do |t|
t.references :payment, foreign_key: true
t.timestamps
end
end
end

View file

@ -606,6 +606,13 @@ ActiveRecord::Schema.define(version: 2021_06_02_220525) do
t.index ["payment_id"], name: "index_offline_transaction_charges_on_payment_id"
end
create_table "offline_transaction_disputes", id: :string, force: :cascade do |t|
t.bigint "payment_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["payment_id"], name: "index_offline_transaction_disputes_on_payment_id"
end
create_table "offline_transaction_refunds", id: :string, force: :cascade do |t|
t.bigint "payment_id"
t.datetime "created_at", precision: 6, null: false
@ -807,13 +814,6 @@ ActiveRecord::Schema.define(version: 2021_06_02_220525) do
t.index ["payment_id"], name: "index_stripe_charges_on_payment_id"
end
create_table "stripe_refunds", id: :string, force: :cascade do |t|
t.bigint "payment_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["payment_id"], name: "index_stripe_refunds_on_payment_id"
end
create_table "stripe_transactions", id: :string, force: :cascade do |t|
t.integer "amount", null: false
t.datetime "created_at", precision: 6, null: false
@ -1046,11 +1046,11 @@ ActiveRecord::Schema.define(version: 2021_06_02_220525) do
add_foreign_key "modern_campaign_gifts", "campaign_gifts"
add_foreign_key "object_event_hook_configs", "nonprofits"
add_foreign_key "offline_transaction_charges", "payments"
add_foreign_key "offline_transaction_disputes", "payments"
add_foreign_key "offline_transaction_refunds", "payments"
add_foreign_key "recurrences", "recurring_donations"
add_foreign_key "recurrences", "supporters"
add_foreign_key "stripe_charges", "payments"
add_foreign_key "stripe_refunds", "payments"
add_foreign_key "subtransaction_payments", "subtransactions"
add_foreign_key "subtransactions", "transactions"
add_foreign_key "ticket_purchases", "event_discounts"

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE
FactoryBot.define do
factory :offline_transaction_dispute do
payment { '' }
end
end

View file

@ -0,0 +1,269 @@
# frozen_string_literal: true
# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE
require 'rails_helper'
RSpec.describe OfflineTransactionDispute, type: :model do
let!(:nonprofit) { create(:nm_justice) }
let!(:supporter) { force_create(:supporter, nonprofit: nonprofit) }
let(:offline_transaction_dispute) do
build(
:offline_transaction_dispute,
payment:
force_create(
:payment,
gross_amount: 500,
net_amount: 400,
fee_total: 100,
date: Time.zone.now,
nonprofit: nonprofit,
supporter: supporter
)
)
end
let(:offline_transaction_charge) do
build(
:offline_transaction_charge,
payment:
force_create(
:payment,
gross_amount: 400,
net_amount: 300,
fee_total: 100,
date: Time.zone.now,
nonprofit: nonprofit,
supporter: supporter
)
)
end
let(:offline_transaction) { build(:offline_transaction) }
let(:transaction) do
trx = supporter.transactions.build(amount: 500)
trx.build_subtransaction(
subtransactable: OfflineTransaction.new(amount: 500),
subtransaction_payments: [
build(:subtransaction_payment, paymentable: offline_transaction_dispute),
build(:subtransaction_payment, paymentable: offline_transaction_charge)
]
)
trx.save!
trx
end
let(:event_publisher) { double }
let(:expected_event) do
{
'data' => {
'object' => {
'created' => kind_of(Numeric),
'fee_total' => { 'cents' => 100, 'currency' => nonprofit.currency },
'gross_amount' => { 'cents' => 500, 'currency' => nonprofit.currency },
'id' => match_houid('offtrxdspt'),
'net_amount' => { 'cents' => 400, 'currency' => nonprofit.currency },
'nonprofit' => {
'id' => nonprofit.id,
'name' => nonprofit.name,
'object' => 'nonprofit'
},
'object' => 'offline_transaction_dispute',
'subtransaction' => {
'created' => kind_of(Numeric),
'id' => match_houid('offlinetrx'),
'initial_amount' => { 'cents' => 500, 'currency' => nonprofit.currency },
'net_amount' => { 'cents' => 700, 'currency' => nonprofit.currency },
'nonprofit' => nonprofit.id,
'object' => 'offline_transaction',
'payments' => [
{
'id' => match_houid('offtrxdspt'),
'object' => 'offline_transaction_dispute',
'type' => 'payment'
}, {
'id' => match_houid('offtrxchrg'),
'object' => 'offline_transaction_charge',
'type' => 'payment'
}
],
'supporter' => supporter.id,
'transaction' => match_houid('trx'),
'type' => 'subtransaction'
},
'supporter' => {
'anonymous' => false,
'deleted' => false,
'id' => supporter.id,
'merged_into' => nil,
'name' => supporter.name,
'nonprofit' => kind_of(Numeric),
'object' => 'supporter',
'organization' => nil,
'phone' => nil,
'supporter_addresses' => [kind_of(Numeric)]
},
'transaction' => {
'amount' => { 'cents' => 500, 'currency' => nonprofit.currency },
'created' => kind_of(Numeric),
'id' => match_houid('trx'),
'nonprofit' => kind_of(Numeric),
'object' => 'transaction',
'subtransaction' => {
'id' => match_houid('offlinetrx'),
'object' => 'offline_transaction',
'type' => 'subtransaction'
},
'subtransaction_payments' => [
{
'id' => match_houid('offtrxdspt'),
'object' => 'offline_transaction_dispute',
'type' => 'payment'
}, {
'id' => match_houid('offtrxchrg'),
'object' => 'offline_transaction_charge',
'type' => 'payment'
}
],
'supporter' => supporter.id,
'transaction_assignments' => []
},
'type' => 'payment'
}
},
'id' => match_houid('objevt'),
'object' => 'object_event',
'type' => 'event_type'
}
end
before do
allow(Houdini)
.to receive(:event_publisher)
.and_return(event_publisher)
transaction
end
describe 'offline transaction dispute' do
subject { offline_transaction_dispute }
it do
is_expected
.to have_attributes(
nonprofit: an_instance_of(Nonprofit),
id: match_houid('offtrxdspt')
)
end
it { is_expected.to be_persisted }
end
describe '.to_builder' do
subject { JSON.parse(offline_transaction_dispute.to_builder.target!) }
it do
is_expected
.to match_json(
{
object: 'offline_transaction_dispute',
nonprofit: kind_of(Numeric),
supporter: kind_of(Numeric),
id: match_houid('offtrxdspt'),
type: 'payment',
fee_total: { cents: 100, currency: nonprofit.currency },
net_amount: { cents: 400, currency: nonprofit.currency },
gross_amount: { cents: 500, currency: nonprofit.currency },
created: kind_of(Numeric),
subtransaction: {
id: match_houid('offlinetrx'),
object: 'offline_transaction',
type: 'subtransaction'
},
transaction: match_houid('trx')
}
)
end
end
describe '.publish_created' do
before do
expected_event['type'] = 'offline_transaction_dispute.created'
allow(event_publisher)
.to receive(:announce)
.with(:payment_created, anything)
allow(event_publisher)
.to receive(:announce)
.with(
:offline_transaction_dispute_created,
expected_event
)
end
it 'announces offline_transaction_dispute.created event' do
offline_transaction_dispute.publish_created
expect(event_publisher)
.to have_received(:announce)
.with(
:offline_transaction_dispute_created,
expected_event
)
end
end
describe '.publish_updated' do
before do
expected_event['type'] = 'offline_transaction_dispute.updated'
allow(event_publisher)
.to receive(:announce)
.with(:payment_updated, anything)
allow(event_publisher)
.to receive(:announce)
.with(
:offline_transaction_dispute_updated,
expected_event
)
end
it 'announces offline_transaction_dispute.updated event' do
offline_transaction_dispute.publish_updated
expect(event_publisher)
.to have_received(:announce)
.with(
:offline_transaction_dispute_updated,
expected_event
)
end
end
describe '.publish_deleted' do
before do
expected_event['type'] = 'offline_transaction_dispute.deleted'
allow(event_publisher)
.to receive(:announce)
.with(:payment_deleted, anything)
allow(event_publisher)
.to receive(:announce)
.with(
:offline_transaction_dispute_deleted,
expected_event
)
end
it 'announces offline_transaction_dispute.deleted event' do
offline_transaction_dispute.publish_deleted
expect(event_publisher)
.to have_received(:announce)
.with(
:offline_transaction_dispute_deleted,
expected_event
)
end
end
end