diff --git a/.circleci/settings.yml b/.circleci/settings.yml index 7c75c595..9a38b134 100644 --- a/.circleci/settings.yml +++ b/.circleci/settings.yml @@ -49,6 +49,9 @@ defaults: &defaults low: 720000 high: 5000000 + fiat_only: + audit_emails: [ 'admin@example.com'] + production: <<: *defaults diff --git a/app/admin/issues.rb b/app/admin/issues.rb index 54184172..8f0f265e 100644 --- a/app/admin/issues.rb +++ b/app/admin/issues.rb @@ -222,6 +222,7 @@ def related_person nf.input :body, input_html: {rows: 3} nf.input :expires_at, as: :datepicker nf.input :archived_at, as: :datepicker + nf.input :note_type ArbreHelpers::Attachment.has_many_attachments(context, nf) end end @@ -526,7 +527,7 @@ def related_person h3 "Current Note Seeds" if seeds = resource.note_seeds.presence ArbreHelpers::Layout.panel_grid(self, seeds) do |d| - attributes_table_for d, :public, :fruit, :created_at, :updated_at, :expires_at + attributes_table_for d, :public, :fruit, :created_at, :updated_at, :expires_at, :note_type para d.body ArbreHelpers::Attachment.attachments_list self, (d.fruit.try(:attachments) || d.attachments) end diff --git a/app/models/admin_user.rb b/app/models/admin_user.rb index 7b842d81..3e8edd80 100644 --- a/app/models/admin_user.rb +++ b/app/models/admin_user.rb @@ -74,6 +74,10 @@ def add_tag(tag) tags.reload end + def fiat_only? + Settings.fiat_only.audit_emails.include? self.email + end + private def set_api_token diff --git a/app/models/currency.rb b/app/models/currency.rb index fa235b01..1834b03c 100644 --- a/app/models/currency.rb +++ b/app/models/currency.rb @@ -2,48 +2,52 @@ class Currency include StaticModels::Model static_models_dense [ - [:id, :code, :name, :decimals ], - [1, :btc, 'bitcoin', 4 ], - [2, :ltc, 'litecoin', 4 ], - [3, :bch, 'bcash', 4 ], - [4, :usd, 'us_dollar', 2 ], - [5, :ars, 'argentine_peso', 2 ], - [6, :uyu, 'uruguayan_peso', 2 ], - [7, :eur, 'euro', 2 ], - [8, :clp, 'chilean_peso', 2 ], - [9, :pen, 'peruvian_sol', 2 ], - [10, :brl, 'brazilian_real', 2 ], - [11, :cop, 'colombian_peso', 2 ], - [12, :mxn, 'mexican_peso', 2 ], - [13, :pyg, 'paraguayan_guarani', 2 ], - [14, :cny, 'chinese_yuan', 2 ], - [15, :inr, 'indian_rupee', 2 ], - [16, :vef, 'venezuelan_bolivar', 2 ], - [17, :aud, 'australian_dollar', 2 ], - [18, :gbp, 'pound_sterling', 2 ], - [19, :hkd, 'hong_kong_dollar', 2 ], - [20, :bob, 'bolivian_peso', 2 ], - [21, :ada, 'ada', 8 ], - [22, :bnb, 'binance_coin', 8 ], - [23, :dai, 'dai', 8 ], - [24, :eth, 'ethereum', 8 ], - [25, :link, 'link', 8 ], - [26, :sushi,'sushi', 8 ], - [27, :uni, 'uni', 8 ], - [28, :usdt, 'usd_tether', 8 ], - [29, :ftt, 'ftt', 8 ], - [30, :yfi, 'yfi', 8 ], - [31, :dot, 'dot', 8 ], - [32, :doge, 'doge', 8 ], - [33, :soya, 'soya', 8 ], - [34, :usdc, 'usdc', 2 ], - [35, :sol, 'sol', 8 ], - [36, :cora, 'cora', 8 ], - [37, :brz, 'brazilian_digital_token', 8 ], - [38, :shib, 'shiba_inu', 8 ], - [39, :mana, 'mana', 8 ], - [40, :chz, 'chiliz', 8 ], - [41, :xlm, 'stellar', 8 ], - [42, :xrp, 'ripple', 8 ], + [:id, :code, :name, :decimals, :type], + [1, :btc, 'bitcoin', 4, :crypto], + [2, :ltc, 'litecoin', 4, :crypto], + [3, :bch, 'bcash', 4, :crypto], + [4, :usd, 'us_dollar', 2, :fiat], + [5, :ars, 'argentine_peso', 2, :fiat], + [6, :uyu, 'uruguayan_peso', 2, :fiat], + [7, :eur, 'euro', 2, :fiat], + [8, :clp, 'chilean_peso', 2, :fiat], + [9, :pen, 'peruvian_sol', 2, :fiat], + [10, :brl, 'brazilian_real', 2, :fiat], + [11, :cop, 'colombian_peso', 2, :fiat], + [12, :mxn, 'mexican_peso', 2, :fiat], + [13, :pyg, 'paraguayan_guarani', 2, :fiat], + [14, :cny, 'chinese_yuan', 2, :fiat], + [15, :inr, 'indian_rupee', 2, :fiat], + [16, :vef, 'venezuelan_bolivar', 2, :fiat], + [17, :aud, 'australian_dollar', 2, :fiat], + [18, :gbp, 'pound_sterling', 2, :fiat], + [19, :hkd, 'hong_kong_dollar', 2, :fiat], + [20, :bob, 'bolivian_peso', 2, :fiat], + [21, :ada, 'ada', 8, :crypto], + [22, :bnb, 'binance_coin', 8, :crypto], + [23, :dai, 'dai', 8, :crypto], + [24, :eth, 'ethereum', 8, :crypto], + [25, :link, 'link', 8, :crypto], + [26, :sushi, 'sushi', 8, :crypto], + [27, :uni, 'uni', 8, :crypto], + [28, :usdt, 'usd_tether', 8, :crypto], + [29, :ftt, 'ftt', 8, :crypto], + [30, :yfi, 'yfi', 8, :crypto], + [31, :dot, 'dot', 8, :crypto], + [32, :doge, 'doge', 8, :crypto], + [33, :soya, 'soya', 8, :crypto], + [34, :usdc, 'usdc', 2, :crypto], + [35, :sol, 'sol', 8, :crypto], + [36, :cora, 'cora', 8, :crypto], + [37, :brz, 'brazilian_digital_token', 8, :crypto], + [38, :shib, 'shiba_inu', 8, :crypto], + [39, :mana, 'mana', 8, :crypto], + [40, :chz, 'chiliz', 8, :crypto], + [41, :xlm, 'stellar', 8, :crypto], + [42, :xrp, 'ripple', 8, :crypto], ] + + def is_fiat? + type == :fiat + end end diff --git a/app/models/fund_deposit.rb b/app/models/fund_deposit.rb index 7a943884..f6cb30f7 100644 --- a/app/models/fund_deposit.rb +++ b/app/models/fund_deposit.rb @@ -33,6 +33,10 @@ def name "##{id}: #{amount} #{currency_code} #{deposit_method_code}" end + def self.deposits_fiat_only_condition + where(currency_id: Currency.all.select(&:is_fiat?)) if AdminUser.current_admin_user&.fiat_only? + end + private def refresh_person_regularity! diff --git a/app/models/fund_transfer.rb b/app/models/fund_transfer.rb index 2b4117f5..6aa812b1 100644 --- a/app/models/fund_transfer.rb +++ b/app/models/fund_transfer.rb @@ -23,4 +23,8 @@ def self.collection_scoped_by_persons where(source_person_id: Person.by_admin_user_tags) .or(FundTransfer.where(target_person_id: Person.by_admin_user_tags)) end + + def self.transfers_fiat_only_condition + where(currency_id: Currency.all.select(&:is_fiat?)) if AdminUser.current_admin_user&.fiat_only? + end end diff --git a/app/models/fund_withdrawal.rb b/app/models/fund_withdrawal.rb index 4170a0b7..6fb0016a 100644 --- a/app/models/fund_withdrawal.rb +++ b/app/models/fund_withdrawal.rb @@ -29,6 +29,10 @@ def name "##{id}: #{amount} #{currency_code} #{country}" end + def self.withdrawals_fiat_only_condition + where(currency_id: Currency.all.select(&:is_fiat?)) if AdminUser.current_admin_user&.fiat_only? + end + private def refresh_person_country_tagging! diff --git a/app/models/note_base.rb b/app/models/note_base.rb index b616c018..9d1db9a0 100644 --- a/app/models/note_base.rb +++ b/app/models/note_base.rb @@ -4,8 +4,12 @@ class NoteBase < ApplicationRecord validates :body, presence: true validates :title, length: { maximum: 255 } + validates :note_type, presence: true def name_body title || body end + + NOTE_TYPE_VALUES = { fiat_note: 1, cripto_note: 2 }.freeze + enum note_type: { unknown: 0 }.merge(NOTE_TYPE_VALUES) end diff --git a/app/models/person.rb b/app/models/person.rb index 6b6e32a3..9e54e3c0 100755 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -46,8 +46,10 @@ class Person < ApplicationRecord HAS_MANY = HAS_MANY_REPLACEABLE + HAS_MANY_PLAIN - has_many :received_transfers, :class_name => 'FundTransfer', :foreign_key => 'target_person_id' - has_many :sent_transfers, :class_name => 'FundTransfer', :foreign_key => 'source_person_id' + has_many :received_transfers, -> { transfers_fiat_only_condition }, :class_name => 'FundTransfer', :foreign_key => 'target_person_id' + has_many :sent_transfers, -> { transfers_fiat_only_condition }, :class_name => 'FundTransfer', :foreign_key => 'source_person_id' + has_many :fund_deposits, -> { deposits_fiat_only_condition } #TODO: check others relations + has_many :fund_withdrawals, -> { withdrawals_fiat_only_condition } #TODO: check others relations has_many :comments, as: :commentable accepts_nested_attributes_for :comments, allow_destroy: true diff --git a/config/settings.example.yml b/config/settings.example.yml index 261bf24e..2a1db5a7 100644 --- a/config/settings.example.yml +++ b/config/settings.example.yml @@ -65,6 +65,9 @@ defaults: &defaults low: 720000 high: 5000000 + fiat_only: + audit_emails: [ 'admin@example.com' ] + production: <<: *defaults diff --git a/db/migrate/20230524141147_add_note_type_to_notes.rb b/db/migrate/20230524141147_add_note_type_to_notes.rb new file mode 100644 index 00000000..38918b19 --- /dev/null +++ b/db/migrate/20230524141147_add_note_type_to_notes.rb @@ -0,0 +1,5 @@ +class AddNoteTypeToNotes < ActiveRecord::Migration[5.2] + def change + add_column :notes, :note_type, :integer, :default => 0, null: false + end +end diff --git a/db/migrate/20230524141334_add_note_type_to_note_seeds.rb b/db/migrate/20230524141334_add_note_type_to_note_seeds.rb new file mode 100644 index 00000000..2a81ba49 --- /dev/null +++ b/db/migrate/20230524141334_add_note_type_to_note_seeds.rb @@ -0,0 +1,5 @@ +class AddNoteTypeToNoteSeeds < ActiveRecord::Migration[5.2] + def change + add_column :note_seeds, :note_type, :integer, :default => 0, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index a40ae480..4a8ef5ff 100755 --- 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.define(version: 2023_03_14_195347) do +ActiveRecord::Schema.define(version: 2023_05_24_141334) do create_table "active_admin_comments", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "namespace" @@ -642,6 +642,7 @@ t.date "expires_at" t.boolean "public", default: false, null: false t.date "archived_at" + t.integer "note_type", default: 0, null: false t.index ["archived_at"], name: "index_note_seeds_on_archived_at" t.index ["fruit_id"], name: "index_note_seeds_on_fruit_id" t.index ["issue_id"], name: "index_note_seeds_on_issue_id" @@ -659,6 +660,7 @@ t.bigint "replaced_by_id" t.boolean "public", default: false, null: false t.date "archived_at" + t.integer "note_type", default: 0, null: false t.index ["archived_at"], name: "index_notes_on_archived_at" t.index ["issue_id"], name: "index_notes_on_issue_id" t.index ["person_id"], name: "index_notes_on_person_id" @@ -834,8 +836,6 @@ t.index ["issue_id"], name: "index_workflows_on_issue_id" end - add_foreign_key "admin_user_taggings", "admin_users" - add_foreign_key "admin_user_taggings", "tags" add_foreign_key "affinities", "affinities", column: "replaced_by_id" add_foreign_key "affinities", "affinity_seeds" add_foreign_key "affinities", "people" diff --git a/spec/models/admin_user_spec.rb b/spec/models/admin_user_spec.rb index bc477e88..6e446020 100644 --- a/spec/models/admin_user_spec.rb +++ b/spec/models/admin_user_spec.rb @@ -37,4 +37,11 @@ admin.disable! expect(admin.active).to eq(false) end + + it 'admin fiat only' do + admin = create(:admin_user) + expect(admin.fiat_only?).to eq(false) + Settings.fiat_only['audit_emails'] = [ admin.email ] + expect(admin.fiat_only?).to eq(true) + end end diff --git a/spec/models/fund_deposit_spec.rb b/spec/models/fund_deposit_spec.rb index 53181713..e5706c8e 100644 --- a/spec/models/fund_deposit_spec.rb +++ b/spec/models/fund_deposit_spec.rb @@ -224,4 +224,18 @@ expect { create(:an_fund_deposit, person: alice) } .not_to change { alice.tags } end + + it 'filter deposits by fiat currencies when user admin is auditor' do + admin_user = create(:admin_user) + AdminUser.current_admin_user = admin_user + Settings.fiat_only['audit_emails'] = [ admin_user.email ] + new_person = create(:empty_person) + create(:full_fund_deposit, person: new_person, currency: Currency.find_by_code('ars')) + create(:full_fund_deposit, person: new_person, currency: Currency.find_by_code('usd')) + create(:full_fund_deposit, person: new_person, currency: Currency.find_by_code('btc')) + create(:full_fund_deposit, person: new_person, currency: Currency.find_by_code('ada')) + fund_deposits = new_person.fund_deposits + expect(fund_deposits.count).to eq 2 + fund_deposits.each { |d| expect(d.currency.is_fiat?).to eq true} + end end diff --git a/spec/models/fund_transfer_spec.rb b/spec/models/fund_transfer_spec.rb index 6ec24836..5fe076f4 100644 --- a/spec/models/fund_transfer_spec.rb +++ b/spec/models/fund_transfer_spec.rb @@ -36,4 +36,23 @@ ) assert_logging(object, :create_entity, 1) end + + it 'filter transfers by fiat currencies when user admin is auditor' do + admin_user = create(:admin_user) + AdminUser.current_admin_user = admin_user + Settings.fiat_only['audit_emails'] = [ admin_user.email ] + + create(:fund_transfer, source_person: source_person, target_person: target_person, currency: Currency.find_by_code('ars')) + create(:fund_transfer, source_person: source_person, target_person: target_person, currency: Currency.find_by_code('usd')) + create(:fund_transfer, source_person: source_person, target_person: target_person, currency: Currency.find_by_code('btc')) + create(:fund_transfer, source_person: source_person, target_person: target_person, currency: Currency.find_by_code('ada')) + + sent_transfers = source_person.sent_transfers + expect(sent_transfers.count).to eq 2 + sent_transfers.each { |d| expect(d.currency.is_fiat?).to eq true } + + received_transfers = target_person.received_transfers + expect(received_transfers.count).to eq 2 + sent_transfers.each { |d| expect(d.currency.is_fiat?).to eq true } + end end diff --git a/spec/models/fund_withdrawal_spec.rb b/spec/models/fund_withdrawal_spec.rb index 2c11d24d..5505251a 100644 --- a/spec/models/fund_withdrawal_spec.rb +++ b/spec/models/fund_withdrawal_spec.rb @@ -75,4 +75,18 @@ expect { create(:an_fund_withdrawal, person: alice) } .not_to change{ alice.tags } end + + it 'filter withdrawals by fiat currencies when user admin is auditor' do + admin_user = create(:admin_user) + AdminUser.current_admin_user = admin_user + Settings.fiat_only['audit_emails'] = [ admin_user.email ] + new_person = create(:empty_person) + create(:full_fund_withdrawal, person: new_person, currency: Currency.find_by_code('ars')) + create(:full_fund_withdrawal, person: new_person, currency: Currency.find_by_code('usd')) + create(:full_fund_withdrawal, person: new_person, currency: Currency.find_by_code('btc')) + create(:full_fund_withdrawal, person: new_person, currency: Currency.find_by_code('ada')) + fund_withdrawal = new_person.fund_withdrawals + expect(fund_withdrawal.count).to eq 2 + fund_withdrawal.each { |d| expect(d.currency.is_fiat?).to eq true} + end end