Ticket purchase json works correctly

This commit is contained in:
Eric Schultz 2021-02-02 15:04:53 -06:00 committed by Eric Schultz
parent 65c56410f1
commit 09b5edaaf8
42 changed files with 1174 additions and 210 deletions

View file

@ -3,8 +3,9 @@
# 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 CampaignGiftOption < ApplicationRecord
include ObjectEvent::ModelExtensions
object_eventable :cgo
include Model::Eventable
include Model::Jbuilder
# :amount_one_time, #int (cents)
# :amount_recurring, #int (cents)
# :amount_dollars, #str, gets converted to amount
@ -29,6 +30,12 @@ class CampaignGiftOption < ApplicationRecord
after_update_commit :publish_updated
after_destroy_commit :publish_deleted
add_builder_expansion :campaign
add_builder_expansion :nonprofit,
to_attrib: -> (model) {model.campaign.nonprofit}
def total_gifts
campaign_gifts.count
end
@ -64,7 +71,7 @@ class CampaignGiftOption < ApplicationRecord
})
end
Jbuilder.new do |json|
init_builder(*expand) do |json|
json.(self, :id, :name, :description,
:hide_contributions, :order, :to_ship)
@ -78,18 +85,6 @@ class CampaignGiftOption < ApplicationRecord
json.amount desc[:amount]
json.recurrence(desc[:recurrence]) if desc[:recurrence]
end
if expand.include? :nonprofit
json.nonprofit campaign.nonprofit.to_builder
else
json.nonprofit campaign.nonprofit.id
end
if expand.include? :campaign
json.campaign campaign.to_builder
else
json.campaign campaign.id
end
end
end

View file

@ -0,0 +1,21 @@
# 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
module Model::Eventable
extend ActiveSupport::Concern
def to_event(event_type, *expand)
Jbuilder.new do |event|
event.id "objevt_" + SecureRandom.alphanumeric(22)
event.object 'object_event'
event.type event_type
event.data do
event.object to_builder(*expand)
end
end
end
def to_builder(*expand)
raise NotImplementedError.new("to_builder must be implemented in your model")
end
end

View file

@ -0,0 +1,44 @@
# 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
module Model::Houidable
extend ActiveSupport::Concern
class_methods do
###
# @description: Simplifies using HouIDs for an ActiveRecord class. HouIDs have the format of:
# prefix_{22 alphanumeric characters}. Prefixes must be unique across an Houdini instance.
# Given a prefix, adds the following features to a ActiveRecord class:
# - Sets a HouID to the id after object initialization (on "after_initialize" callback) if it hasn't already been set
# - Adds a "before_houid_set" and "after_houid_set" callbacks in case you want do somethings before or after that happens
# - Adds "before_houid_set" and "after_houid_set" callbacks if you want to take actions aroun
# - Adds two new public methods:
# - houid_prefix - returns the prefix as a symbol
# - generate_houid - creates a new HouID with given prefix
# @param {string}: the prefix for the HouIDs on this model
###
def setup_houid(prefix)
class_eval <<-RUBY, __FILE__, __LINE__ + 1
define_model_callbacks :houid_set
after_initialize :add_houid
# The HouID prefix as a symbol
def houid_prefix
:#{prefix.to_s}
end
# Generates a HouID using the provided houid_prefix
def generate_houid
houid_prefix.to_s + "_" + SecureRandom.alphanumeric(22)
end
private
def add_houid
run_callbacks(:houid_set) do
write_attribute(:id, self.generate_houid) unless read_attribute(:id)
end
end
RUBY
end
end
end

View file

@ -0,0 +1,95 @@
# 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
module Model::Jbuilder
extend ActiveSupport::Concern
class_methods do
def add_builder_expansion(*args, **kwargs)
builder_expansions.add_builder_expansion(*args, **kwargs)
end
def builder_expansions
@builder_expansions ||= BuilderExpansionSet.new
end
end
class BuilderExpansionSet < Set
def add_builder_expansion(*args, **kwargs)
be = nil
if args.any? || kwargs.any?
if (args.count == 1 && kwargs.any?)
be = BuilderExpansion.new(**{key: args[0]}.merge(kwargs))
add(be)
else
args.each do |a|
be = BuilderExpansion.new(key: a)
add(be)
end
end
else
raise ArgumentError
end
end
def keys
map{|i| i.key}
end
def get_by_key(key)
select{|i| i.key == key}.first
end
end
class BuilderExpansion
include ActiveModel::AttributeAssignment
attr_accessor :key, :json_attrib, :to_id,
:to_expand, :if, :unless, :on_else, :to_attrib
def initialize(new_attributes)
assign_attributes(new_attributes)
end
def json_attrib
@json_attrib || key
end
def to_id
if @to_id
return @to_id
elsif @to_attrib
return -> (model, be=self) { to_attrib.(model).id }
else
return ->(model,be=self) { model.send(be.key).id}
end
end
def to_expand
if @to_expand
return @to_expand
elsif @to_attrib
return -> (model, be=self) { to_attrib.(model).to_builder }
else
return ->(model,be=self) { model.send(be.key).to_builder}
end
end
end
def init_builder(*expand)
builder_expansions = self.class.builder_expansions
Jbuilder.new do | json|
builder_expansions.keys.each do |k|
if expand.include? k
json.set! builder_expansions.get_by_key(k).json_attrib, builder_expansions.get_by_key(k).to_expand.(self)
else
json.set! builder_expansions.get_by_key(k).json_attrib, builder_expansions.get_by_key(k).to_id.(self)
end
end
yield(json)
end
end
end

View file

@ -1,36 +0,0 @@
# 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
module ObjectEvent::ModelExtensions
extend ActiveSupport::Concern
class_methods do
# Adds the to_event method to a model. Requires `to_builder` method for creating
# the Jbuilder object
def object_eventable(prefix)
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def object_prefix
:#{prefix.to_s}
end
def to_event(event_type, *expand)
Jbuilder.new do |event|
event.id "objevt_" + SecureRandom.alphanumeric(22)
event.object 'object_event'
event.type event_type
event.data do
event.object to_builder(*expand)
end
end
end
def to_builder(*expand)
raise NotImplementedError.new("to_builder must be implemented in your model")
end
RUBY
end
end
end

View file

@ -4,6 +4,8 @@
# Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE
class Event < ApplicationRecord
include Image::AttachmentExtensions
include Model::Jbuilder
add_builder_expansion :nonprofit
# :deleted, #bool for soft-delete
# :name, # str
# :tagline, # str

View file

@ -3,8 +3,7 @@
# 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 EventDiscount < ApplicationRecord
include ObjectEvent::ModelExtensions
object_eventable :evtdisc
include Model::Eventable
# :code,
# :event_id,
# :name,

View file

@ -3,6 +3,7 @@
# 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 Supporter < ApplicationRecord
include Model::Jbuilder
# :search_vectors,
# :profile_id, :profile,
# :nonprofit_id, :nonprofit,
@ -49,12 +50,15 @@ class Supporter < ApplicationRecord
has_many :tag_masters, through: :tag_joins
has_many :custom_field_joins, dependent: :destroy
has_many :custom_field_masters, through: :custom_field_joins
has_many :transactions
belongs_to :merged_into, class_name: 'Supporter', foreign_key: 'merged_into'
has_many :merged_from, class_name: 'Supporter', :foreign_key => "merged_into"
validates :nonprofit, presence: true
scope :not_deleted, -> { where(deleted: false) }
add_builder_expansion :nonprofit
# TODO replace with Discard gem
define_model_callbacks :discard
@ -99,7 +103,7 @@ class Supporter < ApplicationRecord
def to_builder(*expand)
supporter_addresses = [self]
Jbuilder.new do |json|
init_builder(*expand) do |json|
json.object "supporter"
json.(self, :id, :name, :organization, :phone, :anonymous, :deleted)
if expand.include? :supporter_address
@ -110,12 +114,6 @@ class Supporter < ApplicationRecord
json.supporter_addresses [id]
end
if expand.include? :nonprofit
json.nonprofit nonprofit.to_builder
else
json.nonprofit nonprofit.id
end
unless merged_into.nil?
if expand.include? :merged_into
json.merged_into merged_into.to_builder
@ -188,6 +186,29 @@ class Supporter < ApplicationRecord
end
end
end
# def new_builder(*expand)
# Jbuilder.new do | json|
# expandable_builders.keys.each do |k|
# if expand.include? k
# json.set! expandable_builders[k][:json_attrib], expandable_builders[k][:expanded].call(self)
# else
# json.set! expandable_builders[k][:json_attrib], expandable_builders[k][:id].call(self)
# end
# end
# yield(json)
# end
# end
# def expandable_builders
# {
# nonprofit: {
# json_attrib: :nonprofit,
# id: ->(model) { model.nonprofit.id},
# expanded: ->(model) { model.nonprofit.to_builder }
# }
# }
# end
end
ActiveSupport.run_load_hooks(:houdini_supporter, Supporter)

View file

@ -3,8 +3,9 @@
# 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 SupporterNote < ApplicationRecord
include ObjectEvent::ModelExtensions
object_eventable :suppnote
include Model::Eventable
include Model::Jbuilder
# :content,
# :supporter_id, :supporter
@ -15,6 +16,15 @@ class SupporterNote < ApplicationRecord
validates :content, length: { minimum: 1 }
validates :supporter_id, presence: true
# TODO replace with Discard gem
add_builder_expansion :supporter
add_builder_expansion :user,
to_id: ->(model) { model.user&.id},
to_expand: ->(model) { model.user&.to_builder}
add_builder_expansion :nonprofit,
to_attrib: -> (model) {model.supporter.nonprofit}
define_model_callbacks :discard
after_discard :publish_deleted
@ -31,27 +41,9 @@ class SupporterNote < ApplicationRecord
end
def to_builder(*expand)
Jbuilder.new do |json|
init_builder(*expand) do |json|
json.(self, :id, :deleted, :content)
json.object 'supporter_note'
if expand.include? :nonprofit
json.nonprofit supporter.nonprofit.to_builder
else
json.nonprofit supporter.nonprofit.id
end
if expand.include? :supporter
json.supporter supporter.to_builder
else
json.supporter supporter.id
end
if expand.include? :user
json.user user&.to_builder
else
json.user user&.id
end
end
end

View file

@ -3,8 +3,10 @@
# 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 TagMaster < ApplicationRecord
include ObjectEvent::ModelExtensions
object_eventable :tagmstr
include Model::Eventable
include Model::Jbuilder
add_builder_expansion :nonprofit
# TODO replace with Discard gem
define_model_callbacks :discard
@ -18,7 +20,7 @@ class TagMaster < ApplicationRecord
validates :name, presence: true
validate :no_dupes, on: :create
after_create :publish_create
after_create_commit :publish_create
belongs_to :nonprofit
has_many :tag_joins, dependent: :destroy
has_one :email_list
@ -41,24 +43,19 @@ class TagMaster < ApplicationRecord
end
def to_builder(*expand)
Jbuilder.new do |tag|
tag.(self, :id, :name, :deleted)
tag.object 'tag_definition'
if expand.include? :nonprofit && nonprofit
tag.nonprofit nonprofit.to_builder
else
tag.nonprofit nonprofit && nonprofit.id
end
init_builder(*expand) do |json|
json.(self, :id, :name, :deleted)
json.object 'tag_definition'
end
end
private
def publish_create
Houdini.event_publisher.announce(:tag_master_created, to_event('tag_master.created', :nonprofit).attributes!)
Houdini.event_publisher.announce(:tag_definition_created, to_event('tag_definition.created', :nonprofit).attributes!)
end
def publish_delete
Houdini.event_publisher.announce(:tag_master_deleted, to_event('tag_master.deleted', :nonprofit).attributes!)
Houdini.event_publisher.announce(:tag_definition_deleted, to_event('tag_definition.deleted', :nonprofit).attributes!)
end
end

View file

@ -3,8 +3,8 @@
# 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 TicketLevel < ApplicationRecord
include ObjectEvent::ModelExtensions
object_eventable :tktlvl
include Model::Jbuilder
include Model::Eventable
# :amount, #integer
# :amount_dollars, #accessor, string
# :name, #string
@ -28,9 +28,13 @@ class TicketLevel < ApplicationRecord
has_many :tickets
belongs_to :event
has_one :nonprofit, through: :event
has_many :event_discounts, through: :event
validates :name, presence: true
validates :event_id, presence: true
validate :amount_hasnt_changed_if_has_tickets, on: :update
scope :not_deleted, -> { where(deleted: [false, nil]) }
@ -99,4 +103,11 @@ class TicketLevel < ApplicationRecord
def publish_delete
Houdini.event_publisher.announce(:ticket_level_deleted, to_event('ticket_level.deleted', :event, :nonprofit, :event_discounts).attributes!)
end
def amount_hasnt_changed_if_has_tickets
if tickets.any?
console.log("YOU can't change amount if tickets already use this #{ticket_level.id}. Please create a new level")
#errors.add(:amount, "can't change amount if tickets already use this level. Please create a new level")
end
end
end

View file

@ -0,0 +1,59 @@
# 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 TicketPurchase < ApplicationRecord
include Model::Houidable
include Model::Jbuilder
setup_houid :tktpur
add_builder_expansion :event, :nonprofit, :supporter
add_builder_expansion :trx,
json_attrib: :transaction
add_builder_expansion :event_discount,
to_id: -> (model) { model.event_discount&.id },
to_expand: -> (model) { model.event_discount&.to_builder }
before_create :set_original_discount
belongs_to :event_discount
belongs_to :event
has_one :transaction_assignment, as: :assignable
has_one :trx, through: :transaction_assignment
has_one :supporter, through: :trx
has_one :nonprofit, through: :supporter
has_many :ticket_to_legacy_tickets
validates :event, presence: true
def to_builder(*expand)
init_builder(*expand) do |json|
json.(self, :id)
json.object 'ticket_purchase'
json.original_discount do
json.percent original_discount
end if original_discount
json.amount do
json.value_in_cents amount
json.currency nonprofit.currency
end
if expand.include? :tickets
json.tickets ticket_to_legacy_tickets do |i|
i.to_builder.attributes!
end
else
json.tickets ticket_to_legacy_tickets.pluck(:id)
end
end
end
private
def set_original_discount
original_discount = event_discount.nil? ? 0 : event_discount.percent
end
end

View file

@ -0,0 +1,46 @@
# 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 TicketToLegacyTicket < ApplicationRecord
include Model::Houidable
include Model::Jbuilder
belongs_to :ticket_purchase
belongs_to :ticket
has_one :ticket_level, through: :ticket
has_one :event, through: :ticket_purchase
has_one :event_discount, through: :ticket_purchase
has_one :supporter, through: :ticket_purchase
has_one :nonprofit, through: :event
delegate :original_discount, to: :ticket_purchase
delegate :checked_in, :deleted, :note, to: :ticket
setup_houid :tkt
add_builder_expansion :ticket_purchase, :ticket_level, :supporter, :event, :nonprofit
add_builder_expansion :event_discount,
to_id: -> (model) { model.event_discount&.id},
to_expand: -> (model) { model.event_discount&.to_builder}
def to_builder(*expand)
init_builder(*expand) do |json|
json.(self, :id, :checked_in, :deleted, :note)
json.object "ticket"
json.amount do
json.value_in_cents amount
json.currency nonprofit.currency
end
if original_discount
json.original_discount do
json.percent original_discount
end
end
end
end
end

29
app/models/transaction.rb Normal file
View file

@ -0,0 +1,29 @@
# 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 Transaction < ApplicationRecord
include Model::Houidable
setup_houid :trx
belongs_to :supporter
has_many :transaction_assignments
has_many :ticket_purchases, through: :transaction_assignments, source: :assignable, source_type: 'TicketPurchase'
validates :supporter, presence: true
def to_builder(*expand)
Jbuilder.new do |json|
json.(self, :id)
json.object 'transaction'
json.supporter supporter.id
json.nonprofit supporter.nonprofit.id
json.amount do
json.value_in_cents amount || 0
json.currency supporter.nonprofit.currency
end
end
end
end

View file

@ -0,0 +1,12 @@
# 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 TransactionAssignment < ApplicationRecord
include Model::Houidable
setup_houid :trxassign
belongs_to :assignable, polymorphic: true
belongs_to :trx, class_name: 'Transaction', foreign_key: "transaction_id"
end

View file

@ -0,0 +1,9 @@
class CreateTransactions < ActiveRecord::Migration[6.1]
def change
create_table :transactions, id: :string do |t|
t.references :supporter, foreign_key: true
t.integer :amount
t.timestamps
end
end
end

View file

@ -0,0 +1,17 @@
class CreateTicketPurchases < ActiveRecord::Migration[6.1]
def change
create_table :ticket_purchases, id: :string do |t|
t.integer :amount
t.integer :original_discount, default: 0
t.references :event_discount, foreign_key: true
t.references :event, foreign_key: true
t.timestamps
end
create_table :transaction_assignments, id: :string do |t|
t.references :transaction, foreign_key: true, type: :string, null: false
t.references :assignable, polymorphic: true, type: :string, index: { unique: true }, null: false
end
end
end

View file

@ -0,0 +1,15 @@
# 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 CreateTicketToLegacyTickets < ActiveRecord::Migration[6.1]
def change
create_table :ticket_to_legacy_tickets, id: :string do |t|
t.references :ticket_purchase, foreign_key: true, type: :string
t.references :ticket, foreign_key: true
t.integer :amount, default: 0
t.timestamps
end
end
end

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 SetDefaultsOnTicketBooleans < ActiveRecord::Migration[6.1]
def change
change_column_default :tickets, :checked_in, from: nil, to: false
change_column_null :tickets, :checked_in, false
change_column_default :tickets, :deleted, from: nil, to: false
change_column_null :tickets, :deleted, false
end
end

View file

@ -2235,6 +2235,35 @@ CREATE SEQUENCE public.ticket_levels_id_seq
ALTER SEQUENCE public.ticket_levels_id_seq OWNED BY public.ticket_levels.id;
--
-- Name: ticket_purchases; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.ticket_purchases (
id character varying NOT NULL,
amount integer,
original_discount integer DEFAULT 0,
event_discount_id bigint,
event_id bigint,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL
);
--
-- Name: ticket_to_legacy_tickets; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.ticket_to_legacy_tickets (
id character varying NOT NULL,
ticket_purchase_id character varying,
ticket_id bigint,
amount integer DEFAULT 0,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL
);
--
-- Name: tickets; Type: TABLE; Schema: public; Owner: -
--
@ -2249,13 +2278,13 @@ CREATE TABLE public.tickets (
supporter_id integer,
event_id integer,
quantity integer,
checked_in boolean,
checked_in boolean DEFAULT false NOT NULL,
bid_id integer,
card_id integer,
payment_id integer,
note text,
event_discount_id integer,
deleted boolean,
deleted boolean DEFAULT false NOT NULL,
source_token_id uuid
);
@ -2314,6 +2343,31 @@ CREATE SEQUENCE public.trackings_id_seq
ALTER SEQUENCE public.trackings_id_seq OWNED BY public.trackings.id;
--
-- Name: transaction_assignments; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.transaction_assignments (
id character varying NOT NULL,
transaction_id character varying NOT NULL,
assignable_type character varying NOT NULL,
assignable_id character varying NOT NULL
);
--
-- Name: transactions; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.transactions (
id character varying NOT NULL,
supporter_id bigint,
amount integer,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL
);
--
-- Name: users; Type: TABLE; Schema: public; Owner: -
--
@ -3214,6 +3268,22 @@ ALTER TABLE ONLY public.ticket_levels
ADD CONSTRAINT ticket_levels_pkey PRIMARY KEY (id);
--
-- Name: ticket_purchases ticket_purchases_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.ticket_purchases
ADD CONSTRAINT ticket_purchases_pkey PRIMARY KEY (id);
--
-- Name: ticket_to_legacy_tickets ticket_to_legacy_tickets_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.ticket_to_legacy_tickets
ADD CONSTRAINT ticket_to_legacy_tickets_pkey PRIMARY KEY (id);
--
-- Name: tickets tickets_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@ -3230,6 +3300,22 @@ ALTER TABLE ONLY public.trackings
ADD CONSTRAINT trackings_pkey PRIMARY KEY (id);
--
-- Name: transaction_assignments transaction_assignments_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.transaction_assignments
ADD CONSTRAINT transaction_assignments_pkey PRIMARY KEY (id);
--
-- Name: transactions transactions_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.transactions
ADD CONSTRAINT transactions_pkey PRIMARY KEY (id);
--
-- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@ -3490,6 +3576,34 @@ CREATE INDEX index_supporters_on_import_id ON public.supporters USING btree (imp
CREATE INDEX index_supporters_on_name ON public.supporters USING btree (name);
--
-- Name: index_ticket_purchases_on_event_discount_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_ticket_purchases_on_event_discount_id ON public.ticket_purchases USING btree (event_discount_id);
--
-- Name: index_ticket_purchases_on_event_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_ticket_purchases_on_event_id ON public.ticket_purchases USING btree (event_id);
--
-- Name: index_ticket_to_legacy_tickets_on_ticket_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_ticket_to_legacy_tickets_on_ticket_id ON public.ticket_to_legacy_tickets USING btree (ticket_id);
--
-- Name: index_ticket_to_legacy_tickets_on_ticket_purchase_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_ticket_to_legacy_tickets_on_ticket_purchase_id ON public.ticket_to_legacy_tickets USING btree (ticket_purchase_id);
--
-- Name: index_tickets_on_event_id; Type: INDEX; Schema: public; Owner: -
--
@ -3511,6 +3625,27 @@ CREATE INDEX index_tickets_on_payment_id ON public.tickets USING btree (payment_
CREATE INDEX index_tickets_on_supporter_id ON public.tickets USING btree (supporter_id);
--
-- Name: index_transaction_assignments_on_assignable; Type: INDEX; Schema: public; Owner: -
--
CREATE UNIQUE INDEX index_transaction_assignments_on_assignable ON public.transaction_assignments USING btree (assignable_type, assignable_id);
--
-- Name: index_transaction_assignments_on_transaction_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_transaction_assignments_on_transaction_id ON public.transaction_assignments USING btree (transaction_id);
--
-- Name: index_transactions_on_supporter_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_transactions_on_supporter_id ON public.transactions USING btree (supporter_id);
--
-- Name: index_users_on_confirmation_token; Type: INDEX; Schema: public; Owner: -
--
@ -3658,6 +3793,38 @@ CREATE INDEX tag_joins_tag_master_id ON public.tag_joins USING btree (tag_master
CREATE UNIQUE INDEX unique_schema_migrations ON public.schema_migrations USING btree (version);
--
-- Name: ticket_to_legacy_tickets fk_rails_062cef70e7; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.ticket_to_legacy_tickets
ADD CONSTRAINT fk_rails_062cef70e7 FOREIGN KEY (ticket_id) REFERENCES public.tickets(id);
--
-- Name: ticket_purchases fk_rails_28d2157787; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.ticket_purchases
ADD CONSTRAINT fk_rails_28d2157787 FOREIGN KEY (event_id) REFERENCES public.events(id);
--
-- Name: transactions fk_rails_4c3b872843; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.transactions
ADD CONSTRAINT fk_rails_4c3b872843 FOREIGN KEY (supporter_id) REFERENCES public.supporters(id);
--
-- Name: transaction_assignments fk_rails_639389404a; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.transaction_assignments
ADD CONSTRAINT fk_rails_639389404a FOREIGN KEY (transaction_id) REFERENCES public.transactions(id);
--
-- Name: active_storage_variant_records fk_rails_993965df05; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@ -3666,6 +3833,14 @@ ALTER TABLE ONLY public.active_storage_variant_records
ADD CONSTRAINT fk_rails_993965df05 FOREIGN KEY (blob_id) REFERENCES public.active_storage_blobs(id);
--
-- Name: ticket_to_legacy_tickets fk_rails_9ea3f9c907; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.ticket_to_legacy_tickets
ADD CONSTRAINT fk_rails_9ea3f9c907 FOREIGN KEY (ticket_purchase_id) REFERENCES public.ticket_purchases(id);
--
-- Name: active_storage_attachments fk_rails_c3b3935057; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@ -3674,6 +3849,14 @@ ALTER TABLE ONLY public.active_storage_attachments
ADD CONSTRAINT fk_rails_c3b3935057 FOREIGN KEY (blob_id) REFERENCES public.active_storage_blobs(id);
--
-- Name: ticket_purchases fk_rails_e2eb419f70; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.ticket_purchases
ADD CONSTRAINT fk_rails_e2eb419f70 FOREIGN KEY (event_discount_id) REFERENCES public.event_discounts(id);
--
-- PostgreSQL database dump complete
--
@ -4160,6 +4343,10 @@ INSERT INTO "schema_migrations" (version) VALUES
('20210114213034'),
('20210115203009'),
('20210115230815'),
('20210119195318');
('20210119195318'),
('20210122184714'),
('20210122203303'),
('20210127193411'),
('20210128215402');

View file

@ -0,0 +1,23 @@
// License: LGPL-3.0-or-later
import type { HouID, HoudiniObject, HoudiniEvent, Amount, IdType} from '../../common';
import type Nonprofit from '..';
import type Event from '.';
import type { TicketLevel , TicketPurchase} from '.';
import type Supporter from '../Supporter';
export interface Ticket extends HoudiniObject<HouID> {
amount: Amount;
checked_in: boolean;
deleted: boolean;
event: IdType | Event;
nonprofit: IdType | Nonprofit;
note: string;
object: 'ticket';
supporter: IdType | Supporter;
ticket_level: IdType | TicketLevel;
ticket_purchase: HouID | TicketPurchase;
}
export type TicketCreated = HoudiniEvent<'ticket.created', Ticket>;
export type TicketUpdated = HoudiniEvent<'ticket.updated', Ticket>;
export type TicketDeleted = HoudiniEvent<'ticket.deleted', Ticket>;

View file

@ -0,0 +1,24 @@
// License: LGPL-3.0-or-later
import type { HouID, HoudiniObject, HoudiniEvent, Amount, IdType} from '../../common';
import type Nonprofit from '..';
import type Event from '.';
import type { EventDiscount, Ticket } from '.';
import Supporter from '../Supporter';
import { Transaction } from '../Supporter';
export interface TicketPurchase extends HoudiniObject<HouID> {
amount: Amount;
event: IdType | Event;
event_discount?: IdType | EventDiscount | null;
nonprofit: IdType | Nonprofit;
object: 'ticket_purchase';
supporter: IdType | Supporter;
tickets: Ticket[] | HouID[];
transaction: HouID | Transaction;
}
export type TicketPurchaseCreated = HoudiniEvent<'ticket_purchase.created', TicketPurchase>;
export type TicketPurchaseUpdated = HoudiniEvent<'ticket_purchase.updated', TicketPurchase>;
export type TicketPurchaseDeleted = HoudiniEvent<'ticket_purchase.deleted', TicketPurchase>;

View file

@ -11,4 +11,6 @@ export default interface Event extends HoudiniObject {
}
export * from './TicketLevel';
export * from './EventDiscount';
export * from './EventDiscount';
export * from './TicketPurchase';
export * from './Ticket';

View file

@ -0,0 +1,18 @@
// License: LGPL-3.0-or-later
import type { Amount, HoudiniObject, IdType, HouID } from "../../common";
import type Nonprofit from '..';
import type Supporter from ".";
/**
* Represents a transaction made by a supporter
*/
export interface Transaction extends HoudiniObject<HouID> {
amount: Amount;
nonprofit: IdType | Nonprofit;
object: 'transaction';
payment_methods: Array<unknown>;
payments: Array<unknown>;
status: string;
supporter: IdType | Supporter;
transaction_assignments: Array<unknown>;
}

View file

@ -22,3 +22,4 @@ export type SupporterDeleted = HoudiniEvent<'supporter_address.deleted', Support
export * from './SupporterNote';
export * from './SupporterAddress';
export * from './Transaction';

View file

@ -0,0 +1,11 @@
# 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 :ticket_purchase do
amount { 1100 }
event_discount { nil }
event { nil }
end
end

View file

@ -0,0 +1,10 @@
# 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 :ticket_to_legacy_ticket do
ticket_purchase { nil }
ticket { nil }
end
end

View file

@ -0,0 +1,10 @@
# 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 :transaction_assignment do
assignable { nil }
transaction { nil }
end
end

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 :transaction do
end
end

View file

@ -88,12 +88,12 @@ describe InsertTickets do
event_discount_id: data[:event_discount_id],
created_at: Time.now,
updated_at: Time.now,
checked_in: nil,
checked_in: false,
bid_id: i + 1,
card_id: nil,
profile_id: nil,
note: nil,
deleted: nil,
deleted: false,
source_token_id: nil
}.with_indifferent_access
end

View file

@ -33,12 +33,12 @@ describe UpdateTickets do
event_discount: event_discount,
created_at: Time.now,
updated_at: Time.now,
checked_in: nil,
checked_in: false,
bid_id: 1,
card_id: nil,
profile_id: nil,
note: nil,
deleted: nil,
deleted: false,
source_token_id: nil,
ticket_level_id: nil
}
@ -54,12 +54,12 @@ describe UpdateTickets do
event_discount_id: event_discount.id,
created_at: Time.now,
updated_at: Time.now,
checked_in: nil,
checked_in: false,
bid_id: 1,
card_id: nil,
profile_id: nil,
note: nil,
deleted: nil,
deleted: false,
source_token_id: nil,
event_id: event.id,
ticket_level_id: nil

View file

@ -4,17 +4,15 @@
# Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE
require 'rails_helper'
RSpec.describe ObjectEvent::ModelExtensions do
RSpec.describe Model::Eventable do
let(:event_type) {'model.event_name'}
class ClassWithoutToBuilder
include ObjectEvent::ModelExtensions
object_eventable :cwotb
include Model::Eventable
end
class ClassWithToBuilder
include ObjectEvent::ModelExtensions
object_eventable :cwtb
include Model::Eventable
def to_builder(*expand)
Jbuilder.new do |json|
@ -22,18 +20,14 @@ RSpec.describe ObjectEvent::ModelExtensions do
end
end
end
it 'raises NotImplementedError when no to_builder is defined by developer' do
obj = ClassWithoutToBuilder.new
expect(obj.object_prefix).to eq :cwotb
expect { obj.to_event event_type}.to raise_error(NotImplementedError)
end
it 'returns an proper event when to_builder is defined by developer' do
obj = ClassWithToBuilder.new
expect(obj.object_prefix).to eq :cwtb
expect(obj.to_event event_type).to eq({
'id' => match(/objevt_[a-zA-Z0-9]{22}/),
'object' => 'object_event',
@ -45,19 +39,4 @@ RSpec.describe ObjectEvent::ModelExtensions do
}
})
end
it 'raises without object_prefix' do
expect do
class ClassWithoutEventablePrefix
include ObjectEvent::ModelExtensions
object_eventable
def to_builder(*expand)
Jbuilder.new do |json|
json.id 1
end
end
end
end.to raise_error(ArgumentError)
end
end

View file

@ -0,0 +1,53 @@
# 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 Model::Houidable do
let(:prefix) { :trxassign}
let(:preset_houid) { "test_eoiathotih"}
let(:default_trxassign){ TransactionAssignment.new }
let(:already_set_houid) {TransactionAssignment.new(id: preset_houid)}
it 'sets houid_prefix' do
expect(default_trxassign.houid_prefix).to eq prefix
end
it 'generates a valid houid' do
expect(default_trxassign.generate_houid).to match_houid(prefix)
end
it 'sets a valid houid as id' do
expect(default_trxassign.id).to match_houid(prefix)
end
it 'will not override an id if already set' do
expect(already_set_houid.id).to eq preset_houid
end
it 'fires the before_houid_set callback' do
class WithBeforeHouidSetCallback < TransactionAssignment
mattr_accessor :callback_handler
before_houid_set ->(model) { self.class.callback_handler.before_houid_set_callback(model) }
end
WithBeforeHouidSetCallback.callback_handler = double('Before Callback Handler')
expect(WithBeforeHouidSetCallback.callback_handler).to receive(:before_houid_set_callback).with(having_attributes(id: nil))
WithBeforeHouidSetCallback.new
end
it 'fires the after_houid_set callback' do
class WithAfterHouidSetCallback < TransactionAssignment
mattr_accessor :callback_handler
after_houid_set ->(model) { self.class.callback_handler.after_houid_set_callback(model) }
end
WithAfterHouidSetCallback.callback_handler = double('After Callback Handler')
expect(WithAfterHouidSetCallback.callback_handler).to receive(:after_houid_set_callback).with(having_attributes(id: match_houid(:trxassign)))
WithAfterHouidSetCallback.new
end
end

View file

@ -11,21 +11,6 @@ RSpec.describe SupporterNote, type: :model do
let(:supporter_note) { supporter.supporter_notes.create(content: content, user: user) }
let(:supporter_base) do
{
'anonymous' => false,
'deleted' => false,
'name' => name,
'organization' => nil,
'phone' => nil,
'supporter_addresses' => [kind_of(Numeric)],
'id'=> kind_of(Numeric),
'merged_into' => nil,
'nonprofit'=> nonprofit.id,
'object' => 'supporter'
}
end
it 'creates' do
expect(supporter_note.errors).to be_empty
end
@ -52,7 +37,7 @@ RSpec.describe SupporterNote, type: :model do
'id' => user.id,
'object' => 'user'
},
'supporter' => supporter_base.merge({'name' => "Fake Supporter Name"})
'supporter' => supporter_to_builder_base.merge({'name' => "Fake Supporter Name"})
}
}
})
@ -83,7 +68,7 @@ RSpec.describe SupporterNote, type: :model do
'id' => user.id,
'object' => 'user'
},
'supporter' => supporter_base.merge({'name' => "Fake Supporter Name"})
'supporter' => supporter_to_builder_base.merge({'name' => "Fake Supporter Name"})
}
}
}).ordered
@ -116,7 +101,7 @@ RSpec.describe SupporterNote, type: :model do
'id' => user.id,
'object' => 'user'
},
'supporter' => supporter_base.merge({'name' => "Fake Supporter Name"})
'supporter' => supporter_to_builder_base.merge({'name' => "Fake Supporter Name"})
}
}
}).ordered

View file

@ -13,51 +13,14 @@ RSpec.describe Supporter, type: :model do
let(:merged_supporter) {nonprofit.supporters.create(name: name, address: address, merged_into: merged_into_supporter, deleted: true) }
let(:merged_into_supporter) {nonprofit.supporters.create(name: merged_into_supporter_name, address: address) }
let(:supporter_base) do
{
'anonymous' => false,
'deleted' => false,
'name' => name,
'organization' => nil,
'phone' => nil,
'supporter_addresses' => [kind_of(Numeric)],
'id'=> kind_of(Numeric),
'merged_into' => nil,
'nonprofit'=> nonprofit.id,
'object' => 'supporter'
}
end
let(:supporter_address_base) do
{
'id' => kind_of(Numeric),
'deleted' => false,
'address' => address,
'city' => nil,
'state_code' => nil,
'zip_code' => nil,
'country' => 'United States',
'object' => 'supporter_address',
'supporter' => kind_of(Numeric)
}
end
let(:nonprofit_base) do
{
'id' => nonprofit.id,
'name' => nonprofit.name,
'object' => 'nonprofit'
}
end
describe 'supporter' do
it 'created' do
supporter_result = supporter_base.merge({
supporter_result = supporter_to_builder_base.merge({
'supporter_addresses' => [
supporter_address_base
supporter_address_to_builder_base
],
'nonprofit' => nonprofit_base
'nonprofit' => nonprofit_to_builder_base
})
expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, {
@ -80,12 +43,12 @@ RSpec.describe Supporter, type: :model do
expect(Houdini.event_publisher).to_not receive(:announce).with(:supporter_updated)
expect(Houdini.event_publisher).to_not receive(:announce).with(:supporter_address_updated)
supporter_result = supporter_base.merge({
supporter_result = supporter_to_builder_base.merge({
'deleted' => true,
'supporter_addresses' => [
supporter_address_base.merge({'deleted' => true})
supporter_address_to_builder_base.merge({'deleted' => true})
],
'nonprofit' => nonprofit_base
'nonprofit' => nonprofit_to_builder_base
})
expect(Houdini.event_publisher).to receive(:announce).with(:supporter_deleted, {
@ -107,16 +70,13 @@ RSpec.describe Supporter, type: :model do
describe 'supporter_address events' do
it 'creates' do
expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything).ordered
expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, {
'id' => match(/objevt_[a-zA-Z0-9]{22}/),
'object' => 'object_event',
'type' => 'supporter_address.created',
'data' => {
'object' => supporter_address_base.merge({
'supporter' => supporter_base
'object' => supporter_address_to_builder_base.merge({
'supporter' => supporter_to_builder_base
})
}
}).ordered
@ -133,9 +93,9 @@ RSpec.describe Supporter, type: :model do
expect(Houdini.event_publisher).to receive(:announce).with(:supporter_deleted, anything)
supporter_address_result = supporter_address_base.merge({
supporter_address_result = supporter_address_to_builder_base.merge({
'deleted' => true,
'supporter'=> supporter_base.merge({'deleted' => true})
'supporter'=> supporter_to_builder_base.merge({'deleted' => true})
})
expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_deleted, {
@ -162,12 +122,12 @@ RSpec.describe Supporter, type: :model do
'object' => 'object_event',
'type' => 'supporter.updated',
'data' => {
'object' => supporter_base.merge({
'object' => supporter_to_builder_base.merge({
'name' => merged_into_supporter_name,
'supporter_addresses' => [
supporter_address_base
supporter_address_to_builder_base
],
'nonprofit' => nonprofit_base
'nonprofit' => nonprofit_to_builder_base
})
}}).ordered
@ -185,9 +145,9 @@ RSpec.describe Supporter, type: :model do
'object' => 'object_event',
'type' => 'supporter_address.updated',
'data' => {
'object' => supporter_address_base.merge({
'object' => supporter_address_to_builder_base.merge({
'city' => 'new_city',
'supporter'=> supporter_base
'supporter'=> supporter_to_builder_base
})
}}).ordered

View file

@ -9,21 +9,28 @@ RSpec.describe TagMaster, type: :model do
let(:name) { "TAGNAME"}
let(:tag_master) { nonprofit.tag_masters.create(name: name) }
let(:np_builder_expanded) { {
'id' => nonprofit.id,
'name' => nonprofit.name,
'object' => 'nonprofit'
}}
it 'creates' do
expect(tag_master.errors).to be_empty
end
it 'announces create' do
expect(Houdini.event_publisher).to receive(:announce).with(:tag_master_created, {
expect(Houdini.event_publisher).to receive(:announce).with(:tag_definition_created, {
'id' => match(/objevt_[a-zA-Z0-9]{22}/),
'object' => 'object_event',
'type' => 'tag_master.created',
'type' => 'tag_definition.created',
'data' => {
'object' => {
'id'=> kind_of(Numeric),
'deleted' => false,
'name' => name,
'nonprofit'=> nonprofit.id,
'nonprofit'=> np_builder_expanded,
'object' => 'tag_definition'
}
}
@ -33,17 +40,17 @@ RSpec.describe TagMaster, type: :model do
end
it 'announces deleted' do
expect(Houdini.event_publisher).to receive(:announce).with(:tag_master_created, anything).ordered
expect(Houdini.event_publisher).to receive(:announce).with(:tag_master_deleted, {
expect(Houdini.event_publisher).to receive(:announce).with(:tag_definition_created, anything).ordered
expect(Houdini.event_publisher).to receive(:announce).with(:tag_definition_deleted, {
'id' => match(/objevt_[a-zA-Z0-9]{22}/),
'object' => 'object_event',
'type' => 'tag_master.deleted',
'type' => 'tag_definition.deleted',
'data' => {
'object' => {
'id'=> kind_of(Numeric),
'deleted' => true,
'name' => name,
'nonprofit'=> nonprofit.id,
'nonprofit'=> np_builder_expanded,
'object' => 'tag_definition'
}
}

View file

@ -0,0 +1,69 @@
# 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 TicketPurchase, type: :model do
include_context :shared_donation_charge_context
describe 'to_builder' do
include_context :shared_donation_charge_context
let(:legacy_free_tickets) do
force_create(:ticket,
event: event,
supporter: supporter,
ticket_level:free_ticket_level,
quantity: 4)
end
let(:legacy_nonfree_tickets) do
force_create(:ticket,
event: event,
supporter: supporter,
ticket_level:ticket_level,
quantity: 3)
end
describe 'full-priced tickets' do
# TODO Why are we manually setting everything here? It's not clear what order things should
# go in for a transaction. Therefore, we don't assume the order for now and just make sure the
# the output of to_builder is right
let(:trx) { force_create(:transaction, supporter: supporter, amount: 1200)}
let(:ticket_purchase) { force_create(:ticket_purchase, trx: trx, event: event, amount: 1200)}
let(:tickets_for_ticket_purchase) do
legacy_free_tickets.quantity.times do |i|
ticket_purchase.ticket_to_legacy_tickets.create(ticket: legacy_free_tickets, amount: legacy_free_tickets.ticket_level.amount)
end
legacy_nonfree_tickets.quantity.times do |i|
ticket_purchase.ticket_to_legacy_tickets.create(ticket: legacy_nonfree_tickets, amount: legacy_nonfree_tickets.ticket_level.amount)
end
end
let(:tktpur_default) do
{
'id' => match_houid('tktpur'),
'object' => 'ticket_purchase',
'nonprofit' => nonprofit.id,
'event' => event.id,
'supporter' => supporter.id,
'tickets' => match_array(ticket_purchase.ticket_to_legacy_tickets.pluck(:id)),
'amount' => {'currency' => 'usd', 'value_in_cents' => 1200},
'original_discount' => { 'percent' => 0},
'event_discount' => nil,
'transaction' => trx.id
}
end
it 'is valid' do
expect(ticket_purchase.to_builder.attributes!).to match(tktpur_default)
end
end
end
end

View file

@ -0,0 +1,198 @@
# 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 TicketToLegacyTicket, type: :model do
include_context :shared_donation_charge_context
let(:legacy_free_tickets) do
force_create(:ticket,
event: event,
supporter: supporter,
ticket_level:free_ticket_level,
quantity: 4)
end
let(:legacy_nonfree_tickets) do
force_create(:ticket,
event: event,
supporter: supporter,
ticket_level:ticket_level,
quantity: 3)
end
describe 'full-priced tickets' do
let(:trx) { force_create(:transaction, supporter: supporter, amount: 1200)}
let(:ticket_purchase) { force_create(:ticket_purchase, trx: trx, event: event)}
let(:tickets_for_ticket_purchase) do
legacy_free_tickets.quantity.times do |i|
ticket_purchase.ticket_to_legacy_tickets.create(ticket: legacy_free_tickets, amount: legacy_free_tickets.ticket_level.amount)
end
legacy_nonfree_tickets.quantity.times do |i|
ticket_purchase.ticket_to_legacy_tickets.create(ticket: legacy_nonfree_tickets, amount: legacy_nonfree_tickets.ticket_level.amount)
end
end
let(:ticket_default) do
{
'id' => match_houid('tkt'),
'checked_in' => false,
'deleted' => false,
'note' => nil,
'object' => 'ticket',
'nonprofit' => nonprofit.id,
'event' => event.id,
'supporter' => supporter.id,
'ticket_purchase' => ticket_purchase.id,
'original_discount' => { 'percent' => 0},
'event_discount' => nil
}
end
let(:free_ticket_default) {
ticket_default.merge({
'ticket_level' => legacy_free_tickets.ticket_level.id,
'amount' => {'currency' => 'usd', 'value_in_cents' => 0}
})
}
let(:nonfree_ticket_default) {
ticket_default.merge({
'ticket_level' => legacy_nonfree_tickets.ticket_level.id,
'amount' => {'currency' => 'usd', 'value_in_cents' => legacy_nonfree_tickets.ticket_level.amount}
})
}
subject { tickets_for_ticket_purchase; TicketToLegacyTicket}
it 'has 7 TicketToLegacyTicket' do
expect(subject.count).to eq 7
end
it 'has 3 pointing at legacy_free_tickets' do
expect(subject.where(ticket: legacy_free_tickets).count).to eq 4
end
it 'has 4 pointing at legacy_nonfree_tickets' do
expect(subject.where(ticket: legacy_nonfree_tickets).count).to eq 3
end
it 'has a valid free_ticket' do
expect(subject.where(ticket: legacy_free_tickets).first.to_builder.attributes!).to match(free_ticket_default)
end
it 'has a valid nonfree ticket' do
expect(subject.where(ticket: legacy_nonfree_tickets).first.to_builder.attributes!).to match(nonfree_ticket_default)
end
it 'has all free checked in' do
legacy_free_tickets.checked_in = true
legacy_free_tickets.note = "NOTE"
legacy_free_tickets.deleted = true
legacy_free_tickets.save!
subject.where(ticket: legacy_free_tickets).each do |item|
json = item.to_builder.attributes!
expect(json).to match(free_ticket_default.merge({
'deleted' => true,
'checked_in' => true,
'note' => "NOTE"
}))
end
end
end
describe 'discounted tickets' do
let(:trx) { force_create(:transaction, supporter: supporter, amount: 960) }
let(:ticket_purchase) { force_create(:ticket_purchase, trx: trx, event: event, event_discount: event_discount, original_discount: 20) }
let(:tickets_for_ticket_purchase) do
legacy_free_tickets.quantity.times do |i|
ticket_purchase.ticket_to_legacy_tickets.create(ticket: legacy_free_tickets, amount: 0)
end
legacy_nonfree_tickets.quantity.times do |i|
ticket_purchase.ticket_to_legacy_tickets.create(ticket: legacy_nonfree_tickets, amount: 320)
end
end
let(:ticket_default) do
{
'id' => match_houid('tkt'),
'checked_in' => false,
'deleted' => false,
'note' => nil,
'object' => 'ticket',
'nonprofit' => nonprofit.id,
'event' => event.id,
'supporter' => supporter.id,
'ticket_purchase' => ticket_purchase.id,
'original_discount' => { 'percent' => 20},
'event_discount' => event_discount.id
}
end
let(:free_ticket_default) {
ticket_default.merge({
'ticket_level' => legacy_free_tickets.ticket_level.id,
'amount' => {'currency' => 'usd', 'value_in_cents' => 0}
})
}
let(:nonfree_ticket_default) {
ticket_default.merge({
'ticket_level' => legacy_nonfree_tickets.ticket_level.id,
'amount' => {'currency' => 'usd', 'value_in_cents' => 320 }
})
}
subject { tickets_for_ticket_purchase; TicketToLegacyTicket}
it 'has 7 TicketToLegacyTicket' do
expect(subject.count).to eq 7
end
it 'has 3 pointing at legacy_free_tickets' do
expect(subject.where(ticket: legacy_free_tickets).count).to eq 4
end
it 'has 4 pointing at legacy_nonfree_tickets' do
expect(subject.where(ticket: legacy_nonfree_tickets).count).to eq 3
end
it 'has a valid free_ticket' do
expect(subject.where(ticket: legacy_free_tickets).first.to_builder.attributes!).to match(free_ticket_default)
end
it 'has a valid nonfree ticket' do
expect(subject.where(ticket: legacy_nonfree_tickets).first.to_builder.attributes!).to match(nonfree_ticket_default)
end
it 'has all free checked in' do
legacy_free_tickets.checked_in = true
legacy_free_tickets.note = "NOTE"
legacy_free_tickets.deleted = true
legacy_free_tickets.save!
subject.where(ticket: legacy_free_tickets).each do |item|
json = item.to_builder.attributes!
expect(json).to match(free_ticket_default.merge({
'deleted' => true,
'checked_in' => true,
'note' => "NOTE"
}))
end
end
end
end

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
require 'rails_helper'
RSpec.describe TransactionAssignment, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View file

@ -0,0 +1,25 @@
# 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 Transaction, type: :model do
include_context :shared_donation_charge_context
describe 'to_builder' do
subject { supporter.transactions.create(amount: 1000).to_builder.attributes!}
it 'will create a proper builder result' do
expect(subject).to match({
'id' => match('trx_[a-zA-Z0-9]{22}'),
'nonprofit' => nonprofit.id,
'supporter' => supporter.id,
'object' => 'transaction',
'amount' => {
'value_in_cents' => 1000,
'currency' => 'usd'
}
})
end
end
end

View file

@ -41,6 +41,45 @@ RSpec.shared_context :shared_donation_charge_context do
let(:stripe_helper) { StripeMock.create_test_helper }
let(:nonprofit_to_builder_base) do
{
'id' => nonprofit.id,
'name' => nonprofit.name,
'object' => 'nonprofit'
}
end
let(:supporter_to_builder_base) do
{
'anonymous' => false,
'deleted' => false,
'name' => name,
'organization' => nil,
'phone' => nil,
'supporter_addresses' => [kind_of(Numeric)],
'id'=> kind_of(Numeric),
'merged_into' => nil,
'nonprofit'=> nonprofit.id,
'object' => 'supporter'
}
end
let(:supporter_address_to_builder_base) do
{
'id' => kind_of(Numeric),
'deleted' => false,
'address' => address,
'city' => nil,
'state_code' => nil,
'zip_code' => nil,
'country' => 'United States',
'object' => 'supporter_address',
'supporter' => kind_of(Numeric)
}
end
around(:each) do |example|
Timecop.freeze(2020, 5, 4) do
StripeMock.start

View file

@ -18,4 +18,8 @@ module Expect
expect(list_of_errors.any? { |e| e[:key].to_s == i[:key].to_s && e[:name].to_s == i[:name].to_s }).to eq(true), "#{i[:key]} should have existed for #{i[:name]}"
end
end
def match_houid(prefix)
match(/#{prefix}_[a-zA-Z0-9]{22}/)
end
end