diff --git a/app/furniture/tobias.rb b/app/furniture/tobias.rb new file mode 100644 index 000000000..0dd845ca6 --- /dev/null +++ b/app/furniture/tobias.rb @@ -0,0 +1,2 @@ +class Tobias +end diff --git a/app/furniture/tobias/beneficiary.rb b/app/furniture/tobias/beneficiary.rb new file mode 100644 index 000000000..44f7a35c3 --- /dev/null +++ b/app/furniture/tobias/beneficiary.rb @@ -0,0 +1,9 @@ +class Tobias + class Beneficiary < Record + self.table_name = "tobias_beneficiaries" + + belongs_to :trust + + has_many :payments + end +end diff --git a/app/furniture/tobias/payment.rb b/app/furniture/tobias/payment.rb new file mode 100644 index 000000000..db0b0d18b --- /dev/null +++ b/app/furniture/tobias/payment.rb @@ -0,0 +1,7 @@ +class Tobias + class Payment < Record + self.table_name = "tobias_payments" + + monetize :amount_cents + end +end diff --git a/app/furniture/tobias/payout.rb b/app/furniture/tobias/payout.rb new file mode 100644 index 000000000..d37aff9fd --- /dev/null +++ b/app/furniture/tobias/payout.rb @@ -0,0 +1,19 @@ +class Tobias + class Payout < ApplicationRecord + self.table_name = "tobias_payouts" + + belongs_to :trust + has_many :beneficiaries, through: :trust + has_many :payments + + monetize :payout_amount_cents + + def issue + per_beneficiary_amount = (payout_amount / beneficiaries.count) + beneficiaries.each do |beneficiary| + + payments.create_with(amount: per_beneficiary_amount).find_or_create_by(beneficiary_id: beneficiary.id) + end + end + end +end diff --git a/app/furniture/tobias/record.rb b/app/furniture/tobias/record.rb new file mode 100644 index 000000000..6763703c1 --- /dev/null +++ b/app/furniture/tobias/record.rb @@ -0,0 +1,9 @@ +class Tobias + class Record < ApplicationRecord + self.abstract_class = true + + def self.model_name + @_model_name ||= ActiveModel::Name.new(self, ::Tobias) + end + end +end diff --git a/app/furniture/tobias/trust.rb b/app/furniture/tobias/trust.rb new file mode 100644 index 000000000..74d13943a --- /dev/null +++ b/app/furniture/tobias/trust.rb @@ -0,0 +1,8 @@ +class Tobias + class Trust < Record + self.table_name = "tobias_trusts" + + has_many :beneficiaries + + end +end diff --git a/db/migrate/20240127063826_create_tobias_payouts.rb b/db/migrate/20240127063826_create_tobias_payouts.rb new file mode 100644 index 000000000..9ae921836 --- /dev/null +++ b/db/migrate/20240127063826_create_tobias_payouts.rb @@ -0,0 +1,27 @@ +class CreateTobiasPayouts < ActiveRecord::Migration[7.1] + def change + create_table :tobias_trusts, id: :uuid do |t| + t.timestamps + end + + create_table :tobias_beneficiaries, id: :uuid do |t| + t.references :trust, type: :uuid, foreign_key: {to_table: :tobias_trusts} + + t.timestamps + end + + create_table :tobias_payouts, id: :uuid do |t| + t.monetize :payout_amount + t.references :trust, type: :uuid, foreign_key: {to_table: :tobias_trusts} + t.timestamps + end + + create_table :tobias_payments, id: :uuid do |t| + t.references :payout, type: :uuid, foreign_key: {to_table: :tobias_payouts} + t.references :beneficiary, type: :uuid, foreign_key: {to_table: :tobias_beneficiaries} + t.monetize :amount + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index d926915c1..6fd3e0a13 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_01_20_034325) do +ActiveRecord::Schema[7.1].define(version: 2024_01_27_063826) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -295,6 +295,38 @@ t.index ["slug", "client_id"], name: "index_spaces_on_slug_and_client_id", unique: true end + create_table "tobias_beneficiaries", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "trust_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["trust_id"], name: "index_tobias_beneficiaries_on_trust_id" + end + + create_table "tobias_payments", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "payout_id" + t.uuid "beneficiary_id" + t.integer "amount_cents", default: 0, null: false + t.string "amount_currency", default: "USD", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["beneficiary_id"], name: "index_tobias_payments_on_beneficiary_id" + t.index ["payout_id"], name: "index_tobias_payments_on_payout_id" + end + + create_table "tobias_payouts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "payout_amount_cents", default: 0, null: false + t.string "payout_amount_currency", default: "USD", null: false + t.uuid "trust_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["trust_id"], name: "index_tobias_payouts_on_trust_id" + end + + create_table "tobias_trusts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "utility_hookups", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "space_id" t.string "name", null: false @@ -326,4 +358,8 @@ add_foreign_key "rooms", "media", column: "hero_image_id" add_foreign_key "space_agreements", "spaces" add_foreign_key "spaces", "rooms", column: "entrance_id" + add_foreign_key "tobias_beneficiaries", "tobias_trusts", column: "trust_id" + add_foreign_key "tobias_payments", "tobias_beneficiaries", column: "beneficiary_id" + add_foreign_key "tobias_payments", "tobias_payouts", column: "payout_id" + add_foreign_key "tobias_payouts", "tobias_trusts", column: "trust_id" end diff --git a/spec/tobias/factories/beneficiary_factory.rb b/spec/tobias/factories/beneficiary_factory.rb new file mode 100644 index 000000000..b1206ba10 --- /dev/null +++ b/spec/tobias/factories/beneficiary_factory.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :tobias_beneficiary, class: "Tobias::Beneficiary" do + + end +end diff --git a/spec/tobias/factories/payout_factory.rb b/spec/tobias/factories/payout_factory.rb new file mode 100644 index 000000000..f027e7300 --- /dev/null +++ b/spec/tobias/factories/payout_factory.rb @@ -0,0 +1,7 @@ +require_relative "trust_factory" + +FactoryBot.define do + factory :tobias_payout, class: "Tobias::Payout" do + association(:trust, factory: :tobias_trust) + end +end diff --git a/spec/tobias/factories/trust_factory.rb b/spec/tobias/factories/trust_factory.rb new file mode 100644 index 000000000..4c1892065 --- /dev/null +++ b/spec/tobias/factories/trust_factory.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :tobias_trust, class: "Tobias::Trust" do + + end +end diff --git a/spec/furniture/tobias/payout_spec.rb b/spec/tobias/payout_spec.rb similarity index 60% rename from spec/furniture/tobias/payout_spec.rb rename to spec/tobias/payout_spec.rb index 31472ed93..ee3e52181 100644 --- a/spec/furniture/tobias/payout_spec.rb +++ b/spec/tobias/payout_spec.rb @@ -1,16 +1,18 @@ require "rails_helper" +require_relative "factories/payout_factory" +require_relative "factories/beneficiary_factory" RSpec.describe Tobias::Payout do describe "#issue" do it "issues a Payment to each Beneficiary for their share of the #payout_amount" do payout = create(:tobias_payout, payout_amount_cents: 150_00) - beneficiaries = create_list(10, :tobias_beneficiary, trust: payout.trust) + beneficiaries = create_list(:tobias_beneficiary, 10, trust: payout.trust) payout.issue beneficiaries.each do |beneficiary| - expect(beneficiary.payments).to exist(amount_cents: 15) + expect(beneficiary.payments).to exist(amount_cents: 15_00) end end end